Shell中變量和命令的各自替換方法,$,${},$(),批量修改文件名


如果對shell命令做替換,可用 $(命令) 或反引號 `命令`:

 1 #命令替換
 2 [liusiyi@localhost ~]$ ls|grep t$             #直接顯示當前目錄下最后一個字符為t的文件名
 3 arg.txt
 4 char.txt
 5 
 6 [liusiyi@localhost ~]$ echo $(ls|grep t$)     #用變量形式,顯示當前目錄下最后一個字符為t的文件名
 7 arg.txt char.txt
 8 
 9 
10 
11 [liusiyi@localhost ~]$ echo `ls|grep t$`        #用``等價於上面的$()
12 arg.txt char.txt
13 
14 
15 #下面這個例子,展示了$()比``的表達更優秀
16 [liusiyi@localhost ~]$ echo $(echo $(ls))    #echo里面嵌套了一個echo $(ls),易懂
17 about.sh aoooo..123.py arg.txt char.txt filemode1.smod.mod.mod file_rm_suffix.sh file_suffix.sh grep grepfolder hello laugh __mana meimei myfolder printargs.sh tempfolder touch
18 
19 [liusiyi@localhost ~]$ echo `echo `ls``      #echo里面嵌套了一個echo `ls`,但結果不是我們需要的;
20 ls
21 [liusiyi@localhost ~]$ echo `echo \`ls\``    #里層的反引號需要轉義處理成 \` 才是我們需要的結果;這樣寫確實啰嗦了些,也容易出錯
22 about.sh aoooo..123.py arg.txt char.txt filemode1.smod.mod.mod file_rm_suffix.sh file_suffix.sh grep grepfolder hello laugh __mana meimei myfolder printargs.sh tempfolder touch
23 
24 
25 #所以結論是建議使用$()做命令替換,而非反引號``

 

 

做變量替換時,可以寫作$變量或 ${變量},具體區別是什么,看這個例子秒懂:

[liusiyi@localhost ~]$ name=Bob

[liusiyi@localhost ~]$ echo $name is a boy
Bob is a boy
[liusiyi@localhost ~]$ echo ${name} is a boy
Bob is a boy

[liusiyi@localhost ~]$ echo $name_is_a_boy     #$name后面如果跟 _,數字,字母等,系統會任務這是一個完整的變量,即#name_

[liusiyi@localhost ~]$ echo ${name}_is_a_boy   #${name}可以很好的規避這類情況
Bob_is_a_boy

[liusiyi@localhost ~]$ echo $name?             #因為shell變量命名規則中是不能包括特殊符號的(比如?、*),所以這次$name?不會被當做一個完整變量
Bob?
[liusiyi@localhost ~]$ echo ${name}?                
Bob?

 

 

 批量修改某個目錄下的文件名,后面加上.mod;然后再把文件名復原,(附.sh腳本):

 1 [liusiyi@localhost ~]$ ls                                 #先看一下home下有哪些文件和文件夾
 2 about.sh       arg.txt   filemode1.smod.mod.mod  file_suffix.sh  grepfolder  laugh   meimei    printargs.sh  touch
 3 aoooo..123.py  char.txt  file_rm_suffix.sh       grep            hello       __mana  myfolder  tempfolder
 4 [liusiyi@localhost ~]$ file_suffix.sh ~                  #運行腳本file_suffix.sh,為每一個文件名后面加.mod
 5 this is a folder: /home/liusiyi/grep
 6 this is a folder: /home/liusiyi/grepfolder
 7 this is a folder: /home/liusiyi/myfolder
 8 [liusiyi@localhost ~]$ ls                                #這時,home下的文件已經都被重命名了
 9 about.sh.mod       char.txt.mod                file_suffix.sh.mod  hello.mod   meimei.mod        tempfolder.mod
10 aoooo..123.py.mod  filemode1.smod.mod.mod.mod  grep                laugh.mod   myfolder          touch.mod
11 arg.txt.mod        file_rm_suffix.sh.mod       grepfolder          __mana.mod  printargs.sh.mod
12 [liusiyi@localhost ~]$  file_rm_suffix.sh.mod ~  #把剛剛加上的.mod去掉;因為我本地本來就存了一份file_rm_suffix.sh,被前一個腳本改成了file_rm_suffix.sh.mod
13 this is a folder: /home/liusiyi/grep
14 this is a folder: /home/liusiyi/grepfolder
15 this is a folder: /home/liusiyi/myfolder
16 [liusiyi@localhost ~]$ ls                        #這時,home下的文件名都恢復了
17 about.sh       arg.txt   filemode1.smod.mod.mod  file_suffix.sh  grepfolder  laugh   meimei    printargs.sh  touch
18 aoooo..123.py  char.txt  file_rm_suffix.sh       grep            hello       __mana  myfolder  tempfolder
[liusiyi@localhost ~]$ cat file_suffix.sh #查看腳本file_suffix.sh
#!/bin/bash

path=$1

for file in `ls $path`
do
        if [ -d $path/$file ]; #如果$path/$file 存在且為一個目錄,則true
                then echo this is a folder: ${path}/${file}
        elif [ -f $path/$file ] ;       #如果存在且為一個普通文件,則true
                then mv ${path}/${file} ${path}/${file}.mod
        else
                echo ${path}/${file} is unknow file type
        fi
done

#-------------------------------------------------------------------------#
[liusiyi
@localhost ~]$ cat file_rm_suffix.sh #查看腳本file_rm_suffix.sh #!/bin/bash path=$1 for file in `ls $path` do if [ -d $path/$file ]; then echo this is a folder: $path/$file elif [ -f $path/$file ]; then mv ${path}/${file} $path/${file%%.mod} #這句${file%%.mod}是拿掉最後一個 .mod 及其右邊的字串,這里用到的一個方法${%%},下面還會詳細說 else echo ${path}/${file} is unknow file type fi done

 

如果想把一串命令都寫在一句,可以用 $(命令1;命令2) 或 ${ 命令1;命令2;},即用分號 ; 把命令串在一起,()和{}有一些區別:

 1 [liusiyi@localhost ~]$ a=test           
 2 [liusiyi@localhost ~]$ echo $a
 3 test
 4 [liusiyi@localhost ~]$ (a=live;echo $a)  #用$()把上面兩句合並在一起,唯一的區別是a=live,隔開命令用分號;
 5 live
 6 [liusiyi@localhost ~]$ echo $a           #因為$()只是對一串命令重新開一個子shell進行執行,所以在當前shell看的話,$a的值還是test
 7 test
 8 [liusiyi@localhost ~]$ {a=live;echo $a}  #現在嘗試用${}運行命令串,這個語法是錯誤的
 9 -bash: {a=live: command not found
10 test}
11 [liusiyi@localhost ~]$ { a=live;echo $a;}#第一個大括號后面要留個空格且大括號里{}每個命令后面都要用分號;
12 live
13 [liusiyi@localhost ~]$ echo $a           #用${}是對一串命令在當前shell執行,所以$a的值真的變成了live
14 live

 

 ${}還有一些奇葩(te shu)用法,${變量:-賦值內容},${變量:=賦值內容},${變量:+賦值內容},${變量:?賦值內容}給變量賦新的值,但是要遵從空或非空的原則,具體如下:

 1 [liusiyi@localhost ~]$ echo $a                #注意:變量a一開始沒賦值,即a值為空
 2 
 3 [liusiyi@localhost ~]$ echo ${a:-newvalue}    #用${變量:-字符串}這種形式給空值a賦值
 4 newvalue
 5 [liusiyi@localhost ~]$ echo $a                #發現a還是一無所有
 6 
 7 [liusiyi@localhost ~]$ unset a
 8 [liusiyi@localhost ~]$ echo ${a:=newvalue}    #用${變量:=字符串}這種形式給空值a賦值
 9 newvalue
10 [liusiyi@localhost ~]$ echo $a                #a終於有了值
11 newvalue
12 
13 [liusiyi@localhost ~]$ unset a
14 [liusiyi@localhost ~]$ echo ${a:+newvalue}    #再來看一下${變量:+字符串}
15 
16 [liusiyi@localhost ~]$ echo $a                #當a為空時,+這個方式是賦不了值的
17 
18 [liusiyi@localhost ~]$ unset a
19 [liusiyi@localhost ~]$ echo ${a:?newvalue}    #再引入一個${變量:?字符串},賦值給空a,它會把后面的字符串輸出到標准錯誤中,並從腳本中退出
20 -bash: a: newvalue
21 [liusiyi@localhost ~]$ echo $a                #a一無所有
22 #以上一輪PK中,當變量a為空時,只有${變量:=字符串}才會真正給空值賦上值,其次是稍有一點點良心的?會打印出標准錯誤,而-和+都不會給空值賦值
23 
24 
25 
26 [liusiyi@localhost ~]$ a=oldvalue             #現在a=old value
27 [liusiyi@localhost ~]$ echo ${a:?newvalue}    #a的值替換了${變量:?字符串},看輸出是oldvalue
28 oldvalue
29 [liusiyi@localhost ~]$ echo $a                #a還是a
30 oldvalue
31 
32 [liusiyi@localhost ~]$ a=oldvalue        
33 [liusiyi@localhost ~]$ echo ${a:=newvalue}    #當a不為空,=根本不改變什么,輸出還是oldvalue
34 oldvalue
35 [liusiyi@localhost ~]$ echo $a                #a還是a,old!
36 oldvalue
37 
38 [liusiyi@localhost ~]$ a=oldvalue                    
39 [liusiyi@localhost ~]$ echo ${a:-newvalue}    #當a不為空,-和上面兩個表現一樣,輸出oldvalue
40 oldvalue
41 [liusiyi@localhost ~]$ echo $a                        #a還是old!
42 oldvalue
43 
44 [liusiyi@localhost ~]$ a=oldvalue
45 [liusiyi@localhost ~]$ echo ${a:+newvalue}    #字符串的值替換了${變量:+字符串},輸出是newvalue耶
46 newvalue
47 [liusiyi@localhost ~]$ echo $a                #a還是a,old!
48 oldvalue
49 #這一輪PK中,當變量a不為空,只有${變量:+字符串}能給a重新賦上值,其他三組都是一樣,不改變a的值。

 用表格來展示是這樣的——

   命令  顯示的值  備注
 變量為空  ${變量:-字符串}  字符串  
   變量  空  
   ${變量:=字符串}  字符串  
   變量  字符串  賦值默認值的常見做法
   ${變量:+字符串}  空  
   變量  空  
   ${變量:?字符串}  字符串被輸出到標准錯誤中,並從腳本中退出 可利用此特性來檢查是否設置了變量的值 
   變量  空  
 變量非空  ${變量:-字符串}  變量  
   變量  變量  
   ${變量:=字符串}  變量  
   變量  變量  
   ${變量:+字符串}  字符串  
   變量  字符串  
   ${變量:?字符串}  變量  
   變量  變量  

 

 

還有${變量#匹配字符},${變量##匹配字符},${變量%匹配字符},${變量%%匹配字符} 這四種模式匹配替換,他們的最終結果都是要刪掉變量中的一部分內容。至於怎么刪,取決於中間的的#和% :

 1 #變量賦值
 2 [liusiyi@localhost ~]$ a=goooxxy_to_shool_xxyzkhk
 3 
 4 #先看${變量#匹配字符},它實現的是:從前往后找到第一個匹配的字符,去掉前面(左邊)的內容——當然也包括去掉第一個匹配的字符
 5 [liusiyi@localhost ~]$ echo ${a#*_}
 6 to_shool_xxyzkhk
 7 [liusiyi@localhost ~]$ echo ${a#_}    #如果匹配字符串寫成 _, 而不是 *_,這樣是找不到的,因為從前往后找的話,變量值里的第一個字符根本不是 _,所以返回的還是一個完整的變量值
 8 goooxxy_to_shool_xxyzkhk
 9 [liusiyi@localhost ~]$ echo ${a#goo}  #這樣是可以的,因為變量的前三個字符就是 goo,沒問題!
10 oxxy_to_shool_xxyzkhk
11 
12 #看${變量##匹配字符},它實現的是:從前往后找到最后一個匹配的字符,去掉前面(左邊)的內容——當然也包括去掉最后一個匹配的字符
13 [liusiyi@localhost ~]$ echo ${a##*_}
14 xxyzkhk
15 
16 #看${變量%匹配字符},它實現的是:從后往前找到第一個匹配的字符,去掉后面(右邊)的內容——當然也包括去掉第一個匹配的字符
17 [liusiyi@localhost ~]$ echo ${a%_*}
18 goooxxy_to_shool
19 
20 #看${變量%%匹配字符},它實現的是:從后往前找到最后一個匹配的字符,去掉后面(右邊)的內容——當然也包括去掉第一個匹配的字符
21 [liusiyi@localhost ~]$ echo ${a%%_*}
22 goooxxy
23 
24 #如果記不住#%對應的到底是從前往后還是從后往前,注意觀察鍵盤,# $ %  正好是【前/左】 【中】 【后/右】
25 #符號#就是從前往后順序的找匹配字符,找到后去掉前面的
26 #符號%就是從后往前倒敘的找匹配字符,找到后去掉后面的
27 #單個符號代表按順序的第一個
28 #雙符號代表按順序的最后一個
29 #用#的時候,如果要用到*,則*放在字符前面
30 #用%的時候,字符在*前面

 

 

 再看一個中間帶冒號 : 的形式,${變量:字符起位置:字符末位置},它的作用是顯示指定位置的變量值內容:

 1 [liusiyi@localhost ~]$ echo $a    
 2 goooxxy_to_shool_xxyzkhk
 3 
 4 [liusiyi@localhost ~]$ echo ${a::10} #顯示前10個字符
 5 goooxxy_to
 6 
 7 [liusiyi@localhost ~]$ echo ${a:3:10} #顯示第3~第10的字符
 8 oxxy_to_sh
 9 
10 [liusiyi@localhost ~]$ echo ${a:3:100}#顯示第3~第100的字符
11 oxxy_to_shool_xxyzkhk
12 
13 [liusiyi@localhost ~]$ echo ${a:5:} #不能省去最后一個冒號后面的數字,否則什么也不輸出

 

 

 用 ${變量/被替換的字符/替換字符} 來替換變量值里的字符:

 1 [liusiyi@localhost ~]$ echo $a    
 2 goooxxy_to_shool_xxyzkhk
 3 
 4 [liusiyi@localhost ~]$ echo ${a/ooo/sss}  #用sss來替換變量值里的ooo
 5 gsssxxy_to_shool_xxyzkhk
 6 
 7 [liusiyi@localhost ~]$ echo ${a/o*/sss}   #用sss來替換變量值里的o*
 8 gsss
 9 
10 [liusiyi@localhost ~]$ echo ${a/_//}      #用 斜杠/ 來替換變量值里的 下划線_
11 goooxxy/to_shool_xxyzkhk
12 
13 [liusiyi@localhost ~]$ echo $a            #替換不改變變量的值
14 goooxxy_to_shool_xxyzkhk

 

 

用 ${#變量} 可統計變量值的個數:

 1 #example1
 2 [liusiyi@localhost ~]$ echo $a    
 3 goooxxy_to_shool_xxyzkhk
 4 
 5 [liusiyi@localhost ~]$ echo ${#a}
 6 24
 7 
 8 #example2
 9 [liusiyi@localhost ~]$ ls
10 a              arg.txt                 file_rm_suffix.sh  grepfolder  __mana    printargs.sh
11 about.sh       char.txt                file_suffix.sh     hello       meimei    tempfolder
12 aoooo..123.py  filemode1.smod.mod.mod  grep               laugh       myfolder  touch
13 
14 [liusiyi@localhost ~]$ a=`ls`
15 
16 [liusiyi@localhost ~]$ echo ${#a}
17 178

 

讀完這些不用的話,確實很容易忘記;但是如果讀別人的代碼時,見過這些規則,至少不會一頭霧水。

END 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM