細讀shell

 1.從使用者的角度來說,使用者也沒辦法直接操作 kernel  而是透過 kernel  "外殼"程序,也就是所謂的 shell  ,來與 kernel  溝通。

每次當我們完成系統登入(log in) 我們就取得一個互動模式的 shell 也稱爲 login she

primary shell 

若從行程(process)角度來說,我們在 shell 所下達的命令,均是 shell 所產生的子行程。

這現像,我們暫可稱之爲 fork

如果是執行腳本(shell script)的話,腳本中的命令則是由另外一個非互動模式的子 shell

(sub shell)來執行的。  也就是 primary shell 產生 sub shell 的行程,sub shell 再產生 script 中所有命令的行程。 

 

2.這裏,我們必須知道:kernel shell 是不同的兩套軟件,而且都是可以被替換的

* 不同的操作系統使用不同的 kernel  

* 而在同一個 kernel 之上,也可使用不同的 shell  

linux 的預設系統中,通常都可以找到好幾種不同的 shell ,且通常會被列於如

裏: 

/etc/shells 

不同的 shell 有着不同的功能,且也彼此各異、或說"大同小異" 

常見的 shell 主要分爲兩大主流: 

sh 

burne shell (sh) 

burne again shell (bash) 

csh 

c shell (csh) 

tc shell (tcsh) 

korn shell (ksh)

3. shell prompt(PS1) Carriage Return(CR) 的關係?

當你成功登錄進一個文字界面之後,大部份情形下,  你會在熒幕上看到一個不斷閃爍的方塊或底線(視不同版本而別)  我們稱之爲*遊標*(coursor)

假如你剛完成登錄還沒輸入任何按鍵之前,你所看到的遊標所在位置的同一行的左邊部份。我們稱之爲*提示符號*(prompt)

$:給一般使用者帳號使用 

#:給 root (管理員)帳號使用

命令行讀進 CR(Carriage Return,由 Enter 鍵產生

所謂的命令行,就是在 shell prompt CR 字符之間所輸入的文字。

 

4.同的命令可接受的命令行格式或有不同, 一般情況下, 一個標準的命令行格式爲如下所列:

command-name options argument 

若從技術細節來看, shell 會依據 IFS(Internal Field Seperator) command line

輸入的文字給拆解爲"字段"(word) 

然後再針對特殊字符(meta)先作處理,最後再重組整行 command line  

其中的 IFS shell 預設使用的字段分隔符,可以由一個及多個如下按鍵組成: 

* 空格鍵(White Space) 

* 表格鍵(Tab) 

* 回車鍵(Enter) 

系統可接受的命令名稱(command-name)可以從如下途徑獲得:

* 明確路徑所指定的外部命令 

* 命令別名(alias) 

* 自定功能(function) 

* shell 內建命令(built-in) 

* $PATH 之下的外部命令 

每一個命令行均必需含用命令名稱,這是不能缺少的。

 

5.關於echo

$ echo -n  不換行輸出

事實上,echo 除了 -n options 之外,常用選項還有: 

-e :啓用反斜線控制字符的轉換(參考下表

-E:關閉反斜線控制字符的轉換(預設如此

-n :取消行末之換行符號( -e 選項下的 \c 字符同意

關於 echo 命令所支持的反斜線控制字符如下表: 

\aALERT / BELL (從系統喇叭送出鈴聲

bBACKSPACE ,也就是向左刪除鍵 

\c:取消行末之換行符號 

\EESCAPE,跳脫鍵 

\fFORMFEED,換頁字符 

\nNEWLINE,換行字符 

\rRETURN,回車鍵 

\tTAB,表格跳位鍵 

\vVERTICAL TAB,垂直表格跳位鍵 

\nASCII 八進位編碼( x 開首爲十六進制

\\:反斜線本身

 

6. 關於command

command line 的每一個 charactor ,分爲如下兩種

* literal:也就是普通純文字,對 shell 來說沒特殊功能。 

* meta shell 來說,具有特定功能的特殊保留字符。 

CR 則是用來結束 command line 用的,這也是爲何我們敲 <enter> 命令就會跑的原

除了 IFS CR ,常用的 meta 還有: 

= 設定變量。 

$ 作變量或運算替換(請不要與 shell prompt 搞混了) 

> :重導向 stdout 

< :重導向 stdin 

|:命令管線。 

& :重導向 file descriptor ,或將命令置於背境執行。 

( ):將其內的命令置於 nested subshell 執行,或用於運算或命令替換。 

{ }:將其內的命令置於 non-named function 中執行,或用在變量替換的界定範圍。

; :在前一個命令結束時,而忽略其返回值,繼續執行下一個命令。 

&& :在前一個命令結束時,若返回值爲 true,繼續執行下一個命令。 

|| :在前一個命令結束時,若返回值爲 false,繼續執行下一個命令。 

!:執行 history 列表中的命令 

.... 

 

7.quoting

bash 中,常用的 quoting 有如下三種方法: 

* hard quote' ' (單引號),凡在 hard quote 中的所有 meta 均被關閉。 

* soft quote " " (雙引號),在 soft quoe 中大部份 meta 都會被關閉,但某些則保留(

$ )(注二

* escape \ (反斜線),只有緊接在 escape (跳脫字符)之後的單一 meta 才被關閉。 

( 注二:在 soft quote 中被豁免的具體 meta 清單,我不完全知道, 

有待大家補充,或透過實作來發現及理解。

代碼:

   $ A=B C   # 空格鍵未被關掉,作爲 IFS 處理。 

   $ C: command not found. 

   $ echo $A 

    

   $ A="B C"   # 空格鍵已被關掉,僅作爲空格鍵處理。 

   $ echo $A 

   B

C

 

   $ A="B 

   > C

> " 

$ echo $A 

B C

 

 $ A=B\ 

   > C\ 

   > 

   $ echo $A 

   BC

 

$ A=B\ C 

   $ echo "$A" 

   B C 

   $ echo '$A' 

   $A

 

  $ A=B\ C 

  $ echo '"$A"'   # 最外面的是單引號 

  "$A" 

  $ echo "'$A'"   # 最外面的是雙引號 

  'B C' 

  (提示:單引號及雙引號,在 quoting 中均被關?#93;了。)

 

8.面我們提到的那些 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 自身的變量無需使用 $ )

要是理解了 hard quote 的功能,再來理解 soft quote escape 就不難:

awk "{print \$0}" 1.txt 

awk \{print\ \$0\} 1.txt

然而,若你要改變 awk $0 0 值是從另一個 shell 變量讀進呢? 

比方說:已有變量 $A 的值是 0 ,那如何在 command line 中解決 awk $$A 呢?  你可以很直接否定掉 hard quoe 的方案:  

$ awk '{print $$A}' 1.txt

那是因爲 $A $ hard quote 中是不能替換變量的。

我想,應該可以解釋爲何我們可以使用如下操作了吧:

代碼:

A=0 

awk "{print \$$A}" 1.txt 

awk \{print\ \$$A\} 1.txt 

awk '{print $'$A'}' 1.txt 

awk '{print $'"$A"'}' 1.txt     # 注:"$A" 包在 soft quote

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章