bash變量替換

1) 賦值「=」和擴充變量值
在設定變量的時侯,得遵照以下規則:
* 等號左右兩邊不能使用區隔符號(IFS),也應避免使用 shell 的保留字符(meta charactor)。
* 變量名稱不能使用 $ 符號。
* 由字母和下劃線組成,而且變量名稱的第一個字母不能是數字(number)。
* 變量名稱長度不可超過 256 個字母。
* 變量名稱及變量值之大小寫是敏感的(case sensitive)
例如:NAME=ice_walk        給變量NAME賦值爲ice_walk 
在應用變量NAME的時候,在NAME前加"$"便可。
例如:echo  $NAME

擴充"(append)變量值:
除了shell中的meta,其它的[^a-zA-Z0-9_]幾乎均可以做單詞邊界。這些功能有時候會在程序中有意想不到的做用。例如:
$ a=bcd 
$ echo $a.php                        得:bcd.php
$ echo $a%b                        得:bcd%b
$ echo /$a/bc                        得:/bcd/bc
對於shell中的meta字符,則使用backslash。
$ echo $a\*b                        得:bcd*b
用戶也能夠在命令行上同時對多個變量賦值,賦值語句之間用空格分開:
  X=x                Y=y                        (注意變量賦值是從右到左進行的)
  X=$Y                Y=y                        X的值是y 
X=z                Y=$Z                        Y的值是空 (變量未賦值時,shell不報錯,而是賦值爲空) 

內置命令eval:
在要求多於一次字符串求值的狀況下可使用內置命令 eval。例如,若是變量 X 有值 $y, 而且若 y 有值 pqr 則:eval echo $X
將回顯字符串 pqr。 
通常的,eval 命令求值它的實際參數(與全部命令同樣)並把這個結果做爲給 shell 的輸入來對待。讀這個輸入並執行做爲結果的命令。例如:
wg=\'eval who|grep\'
$wg fred
等價於:who|grep fred
在這例子中,須要 eval 的緣由是替換以後不解釋元字符如 |。

局部變量
在 BASH 程序中若是一個變量被使用了,那麼直到該程序的結尾,該變量都一直有效。爲了使得某個變量存在於一個局部程序塊中,就引入了局部變量的概念。BASH 中,在變量首次被賦初值時加上 local 關鍵字就能夠聲明一個局部變量。

C-shell的用戶應該注意:
C-shell中的賦值不一樣於Bourne和Korn shell。C-shell使用set命令進行賦值:
$set  LOOK = /usr/mydir      (注意在等號兩邊要加空格,好像不加也能夠)
就象文件名的置換同樣,變量名的置換也是在調用程序前進行。在變量替換中,變量的值取代了變量名。例如在:$ls  $LOOK/filename  用 /usr/mydir/filename 作參數調用ls。

2) 變量替換${}
Shell 之因此強大,其中的一個因素是它能夠在命令行中對變量做替換(substitution)處理。在命令行中使用者可使用 $ 符號加上變量名稱(除了在用 = 號定義變量名稱以外),將變量值給替換出來,而後再從新組建命令行。
通常狀況下,$var 與 ${var} 並無啥不同。可是用 ${ } 會比較精確的界定變量名稱的範圍,比方說:
$ A=B
$ echo $AB
本來是打算先將 $A 的結果替換出來,而後再補一個 B 字母於其後,但在命令行上,真正的結果倒是隻會提換變量名稱爲 AB 的值出來。若使用 ${ } 就沒問題了。

A、掐頭去尾
假設咱們定義了一個變量爲:file=/dir1/dir2/dir3/my.file.txt
咱們可用 ${ } 分別替換得到不一樣的值:
${file#*/}        從變量file的字符串左邊開始刪除字符,直到第一個「/」:dir1/dir2/dir3/my.file.txt
${file##*/}        從變量file的字符串左邊開始刪除字符,直到最後一個「/」:my.file.txt
${file#*.}        從變量file的字符串左邊開始刪除字符,直到第一個「.」:file.txt
${file##*.}        從變量file的字符串左邊開始刪除字符,直到最後一個「.」:txt
${file%/*}        從右部開始拿掉字符,直到遇到(從右部數起的)第一個「/」 :/dir1/dir2/dir3
${file%%/*}        從右部開始拿掉字符,直到遇到(從右部數起的)最後一個「/」:(空值)
${file%.*}        從右部開始拿掉字符,直到遇到(從右部數起的)第一個「.」:/dir1/dir2/dir3/my.file
${file%%.*}        從右部開始拿掉字符,直到遇到(從右部數起的)最後一個「.」:/dir1/dir2/dir3/my
記憶的方法爲:
#                        是去掉左邊(在鍵盤上 # 在 $ 之左邊)
%                        是去掉右邊(在鍵盤上 % 在 $ 之右邊)
單一符號是最小匹配﹔兩個符號是最大匹配。
同時要注意:在 # 和 % 後可使用任何shell中的模式匹配。並不是僅限於*、.、/。

B、字串提取
${file:0:5}        提取最左邊的 5 個字節:/dir1
${file:3}                去掉前面3個字符
${file:5:5}        提取第 5 個字節右邊的連續 5 個字節:/dir2

C、字符串替換
${file/dir/path}                將第一個 dir 提換爲 path:/path1/dir2/dir3/my.file.txt
${file//dir/path}                將所有 dir 提換爲 path:/path1/path2/path3/my.file.txt
不可使用 regexp , 只能用shell中 * 、? 的文件擴展方式。

D、通吃變量名
${!prefix*}                        表明全部以prefix開始的變量名,各變量名稱之間以空格符分隔
$ ab=1 abc=2 abcd=3
$ echo ${!ab*}                        輸出:ab abc abcd

E、變量賦值(沒設定、空值、非空值)
${#myvar}                                計算出變量值的長度
${myvar=default}                 若 $myvar 沒設定,則輸出並取值 default。(保留空值及非空值) 
${myvar:=default}                 若 $myvar 沒設定或爲空值,則輸出並取值 default。(保留非空值)
${myvar+default}                若 $myvar 設定爲空值或非空值,輸出但不取值 default,不然返回空(null)。
${myvar:+default}                若 $myvar 設定爲非空值,輸出但不取值 default,不然返回空(null)。
${myvar-default}                若 $myvar 沒設定,輸出但不取值 default。(保留空值及非空值)
${myvar:-default}                若 $myvar 沒設定或爲空值,輸出但不取值 default。(保留非空值)
${myvar?default}        若 $myvar 沒設定,將 default 輸出至 STDERR。(不取值,保留空值及非空值)
${myvar:?default}                若 $myvar 沒設定或爲空值,將 default 輸出至STDERR。(不取值,保留非空值)


(此表請看下面的圖)



變量替換的值也能夠是` `括起來的命令:$USERDIR={$Mydir:-`pwd`}${var:?message}                        當沒有指定message時,shell將顯示一條默認的消息,例如:  $UNAME=$echo  ${UNAME:?}                        結果顯示:sh:UNAME:parameter null or not set速記法:n        = 慈善家(你沒有才給你)n        + 商人(你有才給換)n        - 假慈善家(代表上纔給)n        ? 牛皮精(只說不作)n        加「:」後,至關於把「空值」也看成「unset」值處理,對有值的變量則無影響F、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 則是將第 4 個組數從新定義爲 xyz。3) 清除賦值:unset <變量>變量一旦通過 unset 取消以後,其結果是將整個變量拿掉,而不只是取消其變量值。以下兩行實際上是很不同的:$ A=$ unset A第一行只是將變量 A 設定爲"空值"(null value),但第二行則讓變量 A 不在存在:$ A=$ echo $A                                打印輸出爲空$ unset A$ echo $A                                打印輸出爲空請務必能識別 null value 與 unset 的本質區別,這在一些進階的變量處理上是很嚴格的。與export同樣,unset 命令行也一樣會做變量替換(這其實就是 shell 的功能之一),所以:A=BB=Cunset $A                                事實上所取消的變量是 B 而不是 A 。4) $( )、` `、$(( ))、(( )) A、$( )與 ` `(反引號) 都是用來作命令替換用(command substitution)的。所謂的命令替換與前面的變量替換差很少,都是用來重組命令行:完成引號裏的命令行,而後將其結果替換出來,再重組命令行。例如:$ echo last sunday is $(date -d "last sunday" +%Y-%m-%d) ,如此即可獲得上一星期天的日期了。在操做上,用 $( ) 或 ` ` 都無所謂,只是我"我的"比較喜歡用 $( ) ,理由是:(1) ` ` 很容易與 ' ' ( 單引號)搞混亂。有時在一些奇怪的字形顯示中,兩種符號是如出一轍的(直豎兩點)。(2) 在多層次的複合替換中,` ` 需要額外的跳脫( \` )處理,而 $( ) 則比較直觀。例如:command1 `command2 `command3` `這是錯的。本來的意圖是要在 command2 `command3` 先將 command3 提換出來給command 2 處理,而後再將結果傳給 command1 `command2 ...` 來處理。然而,真正的結果在命令行中倒是分紅了 `command2 ` 與 `` 兩段。正確的輸入應該是:command1 `command2 \`command3\` `要否則,換成 $( ) 就沒問題了:command1 $(command2 $(command3))不過,$( ) 並非沒有弊端的, ` ` 基本上可用在所有的 unix shell 中使用,若寫成 shell script ,其移植性比較高。而 $( ) 並不見的每一種 shell 都能使用,只能說,若你用 bash2 的話,確定沒問題!例:經過$()實現對某目錄下文件進行操做的功能:#!/bin/bashj=$(ls $1)for k in $jdo  echo "$k"  if [ $k = text ]  then    cat $k  else    echo no text  fidoneB、$(( ))用來做整數運算在 bash 中,$(( )) 的整數運算符號大體有這些:+ - * / :分別爲 "加、減、乘、除"。% :餘數運算& | ^ !:分別爲 "AND、OR、XOR、NOT" 運算。例:$ a=5; b=7; c=2$ echo $(( a+b*c ))      #得19$ echo $(( (a+b)/c ))    #得6$ 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)) ))" | bc644C、用 (( ))重定義變量值或做testinga=5; ((a++)) 可將 $a 重定義爲 6a=5; ((a--)) 則爲 a=4a=5; b=7; ((a < b)) 會獲得 0 (true) 的返回值。常見的用於 (( )) 的測試符號有以下這些:<:小於>:大於<=:小於或等於>=:大於或等於==:等於!=:不等於不過,使用 (( )) 做整數測試時,請不要跟 [ ] 的整數測試搞混亂了。
相關文章
相關標籤/搜索