這篇博客的目的在于加深對于展開和引用的理解,闡釋展開和引用之間聯系。
‘ ‘ :強引用,其中的變量引用不會被替換為變量值,而保持原字符串
” “:弱引用,其中的變量引用會被替換為變量值
如果之前對于’ ‘和” “的理解只停留在上述兩句話的這個階段,那么讀完這篇博客相信你一定會有所收獲。(本文會告訴你什么叫做一萬句頂一句。)
展開
0.展開機制說明
1.路徑名展開 *
2.波浪線展開 ~
3.算術表達式展開 $(()) $[]
4.花括號展開 {}
5.參數展開 $
6.命令替換 $() ` `
0.展開機制說明
echo是一個shell內部命令,作用是在標準輸出中打印出它的文本參數。這里會使用echo命令來對所有展開進行說明,所以這一部分會非常容易理解。
# echo this is a test this is a test
echo將文本參數直接打印出來。
# echo * aa addr.data anaconda-ks.cfg bin Checkos.sh hostch.sh hosts.bak hosts.BAK input ls-output.txt ls.txt Pics ping1.sh poem.txt shoplist.data test1.sh testuser.sh testz.sh tongku.sh
如何工作:
這里echo并沒有直接打印,而是列出了當前工作目錄下的所有文件(除了隱藏文件)及目錄。這說明在echo命令執行前,shell把展開成了另外的東西。在對于通配符的學習中可以知道匹配任意長度的任意字符。當回車鍵被按下時,shell在命令被執行前自動展開當前工作目錄下任何符合條件的文件名,所以echo命令所接收到的不是,而是*所展開成的結果。這就解釋了echo * 執行結果。
1.路徑名展開
在展開機制說明中提到的展開就是一種路徑名展開。
舉例說明
[root@localhost ~]# ls aa Checkos.sh input ping1.sh testuser.sh addr.data hostch.sh ls-output.txt poem.txt testz.sh anaconda-ks.cfg hosts.bak ls.txt shoplist.data tongku.sh bin hosts.BAK Pics test1.sh
/root目錄中內容
[root@localhost ~]# echo h* hostch.sh hosts.bak hosts.BAK
h*展開為目錄下以h開頭的文件名
[root@localhost ~]# echo *h Checkos.sh hostch.sh ping1.sh test1.sh testuser.sh testz.sh tongku.sh
*h展開為目錄下以h結尾的文件名
[root@localhost ~]# echo [[:upper:]]* Checkos.sh Pics
[[:upper:]]*展開為目錄下以大寫字母開頭的文件名
所謂展開就是shell對于命令行參數進行解釋,改變其字面意義上的內容。(理解展開的關鍵)
路徑名展開把參數展開為符合匹配模式的內容。
2.波浪線展開
波浪線~是有特殊含義的。shell會對其進行特定解釋。
兩種用法:
~后跟用戶名,展開為指定用戶的家目錄。
~,不指定用戶名,展開為當前用戶的家目錄。
[root@localhost ~]# echo ~ /root [root@localhost ~]# echo ~cold /home/cold
波浪線展開:shell對~作特殊的解釋說明。
3.算術表達式展開
shell允許算術表達式通過展開來執行。其格式$((expression))或者$[expression]
操作符:+、-、*、/、%、**
注意事項:
算術表達式中空格并不重要,并且表達式可以嵌套。
一對括號可以把子表達式括起來。由此可以簡化嵌套。
舉例說明
[root@localhost ~]# echo $((2+2)) 4 [root@localhost ~]# echo $[2+2] 4 [root@localhost ~]# echo $(($((5**2))*3)) 75 [root@localhost ~]# echo $(((5**2)*3)) 75
算術表達式展開:執行算術表達式,并用結果替換之
4.花括號展開
相當有趣的一種展開。我將其理解為每個選項都選擇一次。
通過實例更容易說明其作用。
[root@localhost ~]# echo Front-{A,B,C}-Back Front-A-Back Front-B-Back Front-C-Back
選項用“,”隔開,ABC三個選項
[root@localhost ~]# echo Number_{1..5} Number_1 Number_2 Number_3 Number_4 Number_5
一系列整數
[root@localhost ~]# echo {Z..A} Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
一系列倒序大寫字母
[root@localhost ~]# echo a{A{1,2},B{3,4}}b aA1b aA2b aB3b aB4b
嵌套模式
注意事項:
{}中不能嵌入空白字符。下面是C前加入一個空白符后的執行結果。
[root@localhost ~]# echo Front-{A,B, C}-Back Front-{A,B, C}-Back
{}可以嵌套。
這種展開最普遍的應用是,創建一系列的文件或目錄列表。
[root@localhost Pics]# mkdir {2015..2017}0{1..9} {2015..2017}{10..12} [root@localhost Pics]# ls 201501 201505 201509 201601 201605 201609 201701 201705 201709 201502 201506 201510 201602 201606 201610 201702 201706 201710 201503 201507 201511 201603 201607 201611 201703 201707 201711 201504 201508 201512 201604 201608 201612 201704 201708 201712
看,相當的快捷方便。
5.參數展開
$變量名 將變量替換為變量值
[root@localhost Pics]# echo $USER root
USER系統定義的變量,變量值為當前用戶名
[root@localhost Pics]# x=10 [root@localhost Pics]# echo $x 10
給x賦值為10,$x會被shell自動替換為10
6.命令替換
命令替換允許我們把一個命令的輸出作為一個展開模式來使用。
格式:$(command) `command`
[root@localhost ~]# which man /usr/bin/man [root@localhost ~]# ls -l `which man` -rwxr-xr-x. 1 root root 102736 Jun 10 2014 /usr/bin/man [root@localhost ~]# ls -l $(which man) -rwxr-xr-x. 1 root root 102736 Jun 10 2014 /usr/bin/man
注意:命令的輸出會被直接當成參數。如果命令輸出不能直接作為下一條命令的參數,將不能正常執行。
例如
[root@localhost ~]# which cp alias cp='cp -i' /usr/bin/cp [root@localhost ~]# ls -l `which cp` ls: invalid option -- ''' Try 'ls --help' for more information.
which cp輸出除文件路徑還有其他內容,ls命令報錯。
引用
shell有許多方式可以完成展開,現在是時候學習怎么來控制展開了。
[root@localhost ~]# echo this is a test this is a test
shell從echo命令的參數列表中刪除多余的空格。
[root@localhost ~]# echo The total is $100.00 The total is 00.00
參數展開把$1 的值替換為一個空字符串,因為1是沒有定義的變量。
這里shell自作主張的對輸入的字符串進行轉換,有時這并不是我們所期望的。
shell提供了引用機制,來有選擇地禁止不需要的展開。
1.雙引號
文本放在放在雙引號之中,shell使用的特殊字符除$、\、`之外都會失去它們的特殊含義,被當做特殊字符對待。
回想上面講到的關于展開的內容,~波浪線展開,{}花括號展開,*等通配符的路徑名展開,單詞分割都被禁止。算術表達式展開,參數展開和命令替換仍然有效。
注:什么是單詞分割
在默認情況下單詞分割會在單詞中尋找空格、制表符和換行符,并把它們看作單詞之間的界定符。它們只作為分隔符使用。
舉例說明
[root@localhost ~]# echo this is a test this is a test
這里多個空格只是作為分隔符使用,在上面這個例子中shell認為給出了四個參數,分別是this、is、a、test,將這四個參數傳遞給echo命令,因此執行結果中看不到多出的空格符的影響。
[root@localhost ~]# echo “this is a test”
this is a test
在這個例子中this is a test 文本被包含在””中,單詞分割被禁止,內嵌的空格不再被當做界定符,而被作為參數的一部分。因此運行結果中輸入的空格被保留了下來。
這里還有一個關于單詞分割的有趣例子,給出運行結果。
[root@localhost ~]# echo $(cal) April 2017 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@localhost ~]# echo "$(cal)" April 2017 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
2.單引號
單引號禁止包含文本的所有展開。
舉例說明
[root@localhost ~]# echo text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER text /root/ls-output.txt /root/ls.txt /root/poem.txt a b cold 4 root
所有展開都被允許。
[root@localhost ~]# echo "text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER" text ~/*.txt {a,b} cold 4 root
只有命令替換,算術表達式展開,參數展開被允許。
[root@localhost ~]# echo 'text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER' text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER
所有展開都被禁止。
3.轉義字符
在雙引號中使用轉義字符,可以有選擇地阻止展開。
[root@localhost ~]# echo "The balance for $USER is:$5.00" The balance for root is:.00
兩個$都被當做參數展開。
[root@localhost ~]# echo "The balance for $USER is:\$5.00" The balance for root is:$5.00
阻止了$5.00的展開,\$被顯示為$。
在雙引號中反斜杠失去它的特殊含義,被當做普通字符。
總結:
《The Linux Command Line》中是這樣說明這一章節的:
隨著我們繼續學習 shell,你會發現使用展開和引用的頻率逐漸多起來,所以能夠很好的理解他們的工作方式很有意義。事實上,可以這樣說,他們是學習 shell 的最重要的主題。 如果沒有準確地理解展開模 式,shell 總是神秘和混亂的源泉,并且 shell 潛在的能力也 浪費掉了。
原創文章,作者:maru,如若轉載,請注明出處:http://www.www58058.com/73499
很明顯,比上次寫的博客都有一個大的提升,主要介紹了符號展開在linux shell中的用法,內容寫的很詳細,也很生動,排版還需要一個提升的過程,加油,加油