在 bash 中,常用的 quoting 有如下三種方法:
1) hard quote:' ' (單引號),凡在 hard quote 中的所有 meta 均被關閉。
2) soft quote: " " (雙引號),在 soft quoe 中大部份 meta 都會被關閉,但某些則保留(如 $ )。
3) escape : \ (反斜線),只有緊接在 escape (逸出字元)之後的單一 meta 才被關閉。
常用的meta
IFS:由 <space> 或 <tab> 或 <enter> 三者之一組成(我們常用 space )。
CR:由<enter> 產生。
IFS 是用來拆解command line 的每一個詞(word)用的,因為shell command line 是按詞來處理的。
而 CR 則是用來結束 command line 用的,這也是為何我們敲 <enter> 命令就會跑的原因。
除了 IFS 與 CR ,常用的 meta 還有:
= : 設定變數。
$ : 作變數或運算替換(請不要與 shell prompt 搞混了)。
> :重導向 stdout。
< :重導向 stdin。
|:命令管線。
& :重導向 file descriptor ,或將命令置於背境執行。
( ):將其內的命令置於 nested subshell 執行,或用於運算或命令替換。
{ }:將其內的命令置於 non-named function 中執行,或用在變數替換的界定範圍。
; :在前一個命令結束時,而忽略其傳回值,繼續執行下一個命令。
&& :在前一個命令結束時,若傳回值為 true,繼續執行下一個命令。
|| :在前一個命令結束時,若傳回值為 false,繼續執行下一個命令。
!:執行 history 列表中的命令
....
例一:假設A=bbbb
jack@ubuntu:~$ echo -e "$A" #echo -e 表示開啟逸出字元,否則如果你有\字元的號,它只是原樣輸出,而不會轉義。
bbbb
jack@ubuntu:~$ echo -e '"$A"' #最外面是單引號
"$A"
jack@ubuntu:~$ echo -e "'"$A"'" #最外面是雙引號
'bbbb'
首先看最外面是什麼符號,單引號表示hard quote,雙引號表示soft quote。
soft quote則$A就是變數啦;若是hard quote那直接就是字串。
在 awk 或 sed 的命令參數中調用之前設定的一些變數時,常會問及為何不能的問題。
要解決這些問題,關鍵點就是:
區分出 shell meta 與 command meta
前面我們提到的那些 meta ,都是在 command line 中有特殊用途的,
比方說 { } 是將其內一系列 command line 置於不具名的函式中執行(可簡單視為 command block ),
但是,awk 卻需要用 { } 來區分出 awk 的命令區段(BEGIN, MAIN, END)。
若你在 command line 中如此輸入:
$ awk {print $0} 1.txt
由於 {} 在 shell 中並沒關閉,那 shell 就將 {print $0} 視為 command block ,
但同時又沒有" ; "符號作命令區隔,因此就出現 awk 的語法錯誤結果。
要解決之,可用 hard quote :
$ awk '{print $0}' 1.txt
上面的 hard quote 應好理解,就是將原本的 {、<space>、$(注三)、} 這幾個 shell meta 關閉,避免掉在 shell 中遭到處理,而完整的成為 awk 參數中的 command meta 。
( 注三:而其中的 $0 是 awk 內建的 field number ,而非 awk 的變數,awk 自身的變數無需使用 $ 。)
實際上可以寫成:
awk"{print \$0}" 1.txt
awk \{print\ \$0\} 1.txt
但是現在我想把awk 的 $0 的 0 值是從另一個 shell 變數讀進,怎麼辦?
如下方式可否:
$ awk '{print $$A}' 1.txt
答案不行,因為 $A 的 $ 在 hard quote 中是不能替換變數的。
使用awk外面的變數可這樣:
A=0
1) awk "{print \$$A}" 1.txt
2) awk \{print\ \$$A\} 1.txt
3) awk '{print $'$A'}'1.txt # $A沒被任何引號隔開(不要以為兩邊有引號就是它的),所以實際上是shell變數啦。
4) awk '{print $'"$A"'}' 1.txt #$A兩邊使用的是雙引號,其它為單引號。
如果要在awk中輸出外部變數怎麼辦?
看特殊形式:awk '{print "abc"}' #print後面的字串要用雙引號
一般形式: awk '{print "'$A'"}' # $A左右兩邊都有單引號,其實就是上面的3)式。