簡單而言,command line的每一個charactor分爲如下兩種:
*literal:也就是普通純文字,對shell來說沒有特殊功能。
*meta:對shell來說,具有特定功能的保留字。
literal沒有什麼好說的,凡是 abcd、123456 等這些“文字”都是literal。但是meta確常使我們困惑。事實上,前兩章我們在command line中已碰到兩個幾乎每次都會碰到的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 列表中的命令
....
假如我們要在command line中將這些保留元字符的功能關閉的話,就要用到 quoting 處理了。
在bash中,我們常用的 quoting有如下三種方法:
*hard quote:''(單引號),凡在hard quote中的所有meta均被關閉。
*soft quote:""(雙引號),在soft quote中的大部分meta都會被關閉,但某些保留(如$)。
*escape:\ (反斜線),只有緊接在escape(跳脫字符)之後的單一meta才被關閉。
$ A=B C # 空白鍵未被關閉,作爲IFS 處理。
$ C: command not found.
$ echo $A
$ A="B C" # 空白鍵已被關閉,僅作空白符號處理。
$ echo $A
B C
一、echo 單引號、雙引號和不加引號的區別
單引號會無視其中的所有特殊符號,雙引號中有三種特殊字符不被忽略:$,\,`
,不加引號則不忽略所有特殊字符。例如,編寫一個shell腳本,
- [lfs@lfs tmp]$ a='b c'
- [lfs@lfs tmp]$ echo $a
- b c
- lfs@lfs tmp]$ echo '$a'
- $a
下面的例子中,第二個命令由於沒有關閉()這個meta,命令執行的時候shell首先解釋(),當然出現錯誤了。
- [lfs@lfs tmp]$ echo '('$a')'
- (b c)
- [lfs@lfs tmp]$ echo ($a)
- -bash: syntax error near unexpected token `$a'
下面的例子中,因爲單引號被雙引號括起來,所以shell不會解釋單引號,單引號就會被echo命令顯示
- [lfs@lfs tmp]$ echo "('$a')"
- ('b c')
考慮一下爲什麼下面的例子和上面的輸出結果不一樣。
- [lfs@lfs tmp]$ echo '("$a")'
- ("$a")
這將打印: this is the 2nd
名爲date,內容如下:
echo '$USER date *'
echo "$USER date *"
echo $USER date *
date
當前文件夾下有2個文件,分別爲date和welcome,運行date輸出結果爲:
$USER date *
root date *
root date date welcome
在win下創建的XX.sh文件,在linux上執行,經常執行失敗。對比能執行的文件,沒有發現什麼不同。
執行shell出現的錯誤是bad interpreter:No such file or directory
解決方法:
因爲操作系統是windows,在windows下編輯的腳本,所以有可能有不可見字符。從的腳本及報告的錯誤看來, 很有可能是腳本文件是DOS格式的, 即每一行的行尾以\r\n來標識, 其ASCII碼分別是0x0D, 0x0A.
可以有很多種辦法看這個文件是DOS格式的還是UNIX格式的, 還是MAC格式的。
linux的換行\n,
然後用命令
:set ff
可以看到dos或unix的字樣. 如果的確是dos格式的, 那麼你可以用set ff=unix把它強制爲unix格式的, 然後存盤退出. 再運行一遍.
(2) 用od -t x1 filename
如果你看到有0d 0a 這樣的字符, 那麼它是dos格式的, 如果只有0a而沒有0d, 那麼它是UNIX格式的, 同樣可以用上述方法把它轉爲UNIX格式的.
1. unix2dos或dos2unix這兩個小程序來做. 很簡單. 在djgpp中這兩個程序的名字叫dtou和utod, u代表unix, d代表dos
2. 也可以用sed 這樣的工具來做:
sed 's/^M//' filename > tmp_filename
mv -f tmp_filename filename
來做