1. 程式人生 > >shell中$(( ))和$[]與$( )還有${ }的區別

shell中$(( ))和$[]與$( )還有${ }的區別

n) 變量替換 ask 進制 不足 都是 反引號 arr not

$( )與` `(反引號)


在bash shell中,$( )與` `(反引號)都是用來做命令替換(command substitution)用的。

# echo `which who`

# echo $(which who)

/usr/bin/who

他們得到的結果都是相同的


用$( )的理由


1. ` `很容易與' '(單引號)搞混。有時在一些奇怪的字形顯示中,兩種符號是一模一樣的(直豎兩點)。

2. 在多層次的復合替換中,` `須要額外的跳脫(\`)處理,而$( )則比較直觀。例如:

command1 `command2 `command3` `

原本的意圖是在command2 `command3`中先將command3替換出來給command2處理,然後再將結果傳給command1 `command2 ...`來處理。

然而,真正的結果在命令行中卻是分成了`command2`與` `兩段。

正確的輸入應該如下:

command1 `command2 \`command3\` `

換成$( )則一目了然:

command1 $(command2 $(command3))


# echo `ll `which who``

total 0which who

# echo `ll \`which who\``

-rwxr-xr-x. 1 root root 49872 Nov 6 2016 /usr/bin/who

# echo $(ll `which who`)

-rwxr-xr-x. 1 root root 49872 Nov 6 2016 /usr/bin/who

# echo $(ll $(which who))

-rwxr-xr-x. 1 root root 49872 Nov 6 2016 /usr/bin/who


$( )的不足


``基本上可在全部的unix shell中使用,若寫成shell script移植性比較高。而$()並不是每一種shell都能使用。


${ }用來作變量替換


一般情況下,$var與${var}作用相同。但是用${ }會比較精確的界定變量名稱的範圍,例如:

# A=B

# echo $AB

原本是打算先將$A的結果替換出來,然後再補一個B字母於其後,但在命令行上,真正的結果卻是只會替換變量名稱為AB的值出來。

使用${ }就沒問題了:

# echo ${A}B

BB


${ }的一些特異功能


定義一個變量:

file=/dir1/dir2/dir3/my.file.txt

可以用${ }分別替換獲得不同的值:

${file#*/} 拿掉第一個 / 及其左邊的字符串:dir1/dir2/dir3/my.file.txt

${file##*/} 拿掉最後一個 / 及其左邊的字符串:my.file.txt

${file#*.} 拿掉第一個 . 及其左邊的字符串:file.txt

${file##*.} 拿掉最後一個 . 及其左邊的字符串:txt

${file%/*} 拿掉最後一個 / 及其右邊的字符串:/dir1/dir2/dir3

${file%%/*} 拿掉第一個 / 及其右邊的字符串:(空值)

${file%.*} 拿掉最後一個 . 及其右邊的字符串:/dir1/dir2/dir3/my.file

${file%%.*} 拿掉第一個 . 及其右邊的字符串:/dir1/dir2/dir3/my


單一符號是最小匹配,兩個符號是最大匹配。

${file:0:5} 提取最左邊的 5 個字節:/dir1

${file:5:5} 提取第 5 個字節右邊的連續 5 個字節:/dir2


也可以對變量值裏的字符串作替換:

${file/dir/path} 將第一個 dir 替換為 path:/path1/dir2/dir3/my.file.txt

${file//dir/path} 將全部 dir 替換為 path:/path1/path2/path3/my.file.txt


${#var} 可計算出變量值的長度:

echo ${#file} 輸出 27

/dir1/dir2/dir3/my.file.txt 剛好是 27 個字節。


bash數組(array)處理方法


一般而言,A="a b c def"只是將 $A 替換為一個單一的字符串,但是改為 A=(a b c def),則是將 $A 定義為數組。

bash的數組替換方法可參考如下方法:

${A[@]} 或 ${A[*]} 得到 a b c def(全部數組)

${A[0]} 得到 a (第一個元素),${A[1]} 第二個...

${#A[@]} 或 ${#A[*]} 得到 4 (數組數量)

${#A[0]} 得到 1 (第一個元素 a 的長度),${#A[3]} 得到 3 (第四個元素 def 的長度)

A[3]=xyz 將第四個元素重新定義為 xyz


$(( ))和$[ ]的用途一致


用來作整數運算。在 bash 中,$(( ))的整數運算符號大致有這些:

+ - * / 加、減、乘、除

% 余數運算

& | ^ ! AND、OR、XOR、NOT運算

舉例:

# a=5; b=7; c=2

# echo $((a+b*c))

# echo $[a+b*c]

19

# echo $(((a+b)/c))

# echo $[(a+b)/c]

6

# echo $(((a*b)%c))

# echo $[(a*b)%c]

1

在$(( ))中的變量名稱也可以在其前面加 $ 符號:$(($a+$b*$c))也可以得到 19 的結果。

此外,$(( ))還可以作不同進制(如二進制、八進位、十六進制)運算,只是輸出結果皆為十進制而已。

echo $((16#2a)) 結果為 42 (16進位轉十進制)

舉一個實用的例子:

當前的 umask 是 022,新建文件的權限為:

# umask 022

# echo "obase=8; $(( 8#666 & (8#777 ^ 8#$(umask)) ))" | bc

# 644

事實上,單純用(( ))也可以重定義變量值,或作testing:

# a=5

# echo $((a++))

將 a 重定義為 6

# echo $[a--]

# 5

# echo $((a--))

# 4

a=5; b=7; ((a < b));echo $? 會得到 0 (true) 的返回值

常見的用於(( ))的測試符號有以下這些:

< 小於

> 大於

<= 小於或等於

>= 大於或等於

== 等於

!= 不等於


shell中$(( ))和$[]與$( )還有${ }的區別