1. 程式人生 > >shell 命令執行順序 一

shell 命令執行順序 一

shell 命令執行順序

shell執行命令順序

shell執行命令的步驟順序如上圖,看起來有些複雜。
當命令列被處理時,每一個步驟都是在Shell的記憶體裡發生的;Shell不會真的把每個步驟的發生顯示給你看。
所以,你可以假想這事我們偷窺Shell記憶體裡的情況,從而知道每個階段的命令列是如何被轉換的。

shell執行命令的原理
Shell 從標準輸入或指令碼中讀取的每一行稱為管道(pipeline);它包含了一個或多個命令(command),這些命令被一個或多個管道字元(|)隔開。

對於每一個讀取的管道,Shell都會將命令分割,為管道設定 I/O,並且對每一個命令依次執行下面的操作:

  • 將命令分割成令牌(token),令牌之間以元字元分隔。
    Shell的元字元集合是固定不變的,包括空格、Tab鍵、換行字元、分號(;)、小括號、輸入重定向符(<)、輸出重定向符(>)、管道符(|)和 &符號,令牌可以是單詞(word)、關鍵字,也可以是I/O重定向器和分號。

  • 檢查第一個token是不是一個不帶(引號或反斜槓)開放的關鍵字,if、while、for或其他控制結構中的開始符號
    如果是Shell就認為此命令是複合命令,併為該複合命令進行內部設定,讀取下一條命令,再次啟動程序。
    如果此令牌不是複合命令的開始符號,如該令牌是then、else、do、fi、done等符號,這說明該令牌不應該處在命令列的首位,因此,Shell提示語法錯誤資訊。

  • 按別名檢查每個命令的第一個關鍵字是不是一個別名,如果是,則用其別名定義替換,然後回退到第一步

  • 執行花括號 { } 擴充套件

  • 執行 ~ 擴充套件
  • 執行變數擴充套件
  • 執行命令替換
  • 執行算術表示式計算
  • 把生成的新命令按IFS分割成token
  • 執行路徑擴充套件
  • 按優先順序查詢命令,先從內建,再從path
  • 設定好重定向等,執行命令

花括號擴充套件

  • 簡單點說就是給一組字串加上相同的字首和字尾,生成一組新的字串。字首和字尾都可以為空
Administrator@AAA MINGW64 ~/Desktop/github/git (master)
$ echo a{b,c}d   
abd acd   
Administrator@AAA MINGW64 ~/Desktop/github/git (master)
$ echo a{b,c}   
ab ac  
  • 可以使用一個範圍,只支援數字和字母
Administrator
@AAA MINGW64 ~/Desktop/github/git (master) $ echo a{1..10} a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 Administrator@AAA MINGW64 ~/Desktop/github/git (master) $ echo a{b..l} ab ac ad ae af ag ah ai aj ak al Administrator@AAA MINGW64 ~/Desktop/github/git (master) $ echo 您{好,吃了嗎}? 您{好,吃了嗎}
  • 花括號還可以巢狀,逐層有序的進行處理
    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo a{{1,2},{b,c}}   
    a1 a2 ab ac  

這個過程可以理解為先生成a{1,2,b,c},然後生成 a1 a2 ab ac

要注意的地方
1. 花括號裡只有字面量。不支援變數:

    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ a=1  
    $ echo a{a..10}   
    {1..10}

並沒有像之前一樣生成1,2,3,4..10。對花括號擴充套件來說,生成的結果是{$a..10},那為什麼我們看到的結果是{1..10}呢?這就是shell的命令處理順序有關係了,我們在看shell的命令處理順序,花括號擴充套件是在第4布,到了第6步,才會執行變數擴充套件,這時候相當於命令

  [email protected] MINGW64 ~/Desktop/github/git (master)
  echo {$a..10}   

先執行 echo{$a..10},在執行變數擴充套件 $a被替換成1,因此輸出 {1..10}

  1. 花括號裡至少要有一個逗號,至少要有兩項
  2. 兩項之間不能有空格,逗號前後不能有空格,否則不進行花括號擴充套件

波浪號擴充套件

波浪號擴充套件就是對 ~ 進行處理。
一般情況下,我們認為 ~ 代表了當前的主目錄。但是並非這麼簡單。進行波浪號替換的條件是很苛刻的

首先,進行波浪號擴充套件的前提是波浪號必須位於一個 token 的開頭,簡單的說 ~ 前面應該是空格

然後,shell會分析波浪號之後,第一個 / 或 : 之前的未被引號括起來的字串(如果沒有 / 那就取波浪號之後的所有字元)這個字元叫做”波浪號字首(tilde-prefix)”(注意,所謂波浪號字首其實是出現在波浪號後面的),波浪號字首的取值和對應的處理方式是:

  1. 如果波浪號字首是個有效使用者名稱,則波浪號和波浪號字首一起替換成使用者的主目錄

  2. 如果波浪號字首為空,則嘗試把波浪號替換成HOME,如果HOME沒有被設定,則將波浪號替換成當前使用者主目錄

  3. 如果波浪號字首是 + 則 ~+ 被替換成當前工作目錄(pwd)

  4. 如果波浪字首是 - 則 ~- 被替換成上一個工作目錄 (OLDPWD)

  5. 如果波浪號字首是個數字 n 則把 ~n 替換成目錄堆疊 (用 dirs 命令可以檢視目錄堆疊)的第n個元素(這個沒有什麼用)
    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo ~
    /c/Users/Administrator/Desktop/github/git  

波浪號被替換成當前使用者主目錄

    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo /~ 
    /~       

波浪號不在token的開頭,不進行擴充套件

    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo ~root 
    /root
    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo ~root/ 
    /root/
    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo ~+
     /c/Users/Administrator/Desktop/github/git

波浪號被替換成當前工作目錄


    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo ~-
    ~-   

波浪號替換成上一個目錄,因為沒用cd,上一個目錄OLDPWD沒有設定,替換失敗原樣輸出

    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ cd Markdown
    [email protected] MINGW64 ~/Desktop/github/git (master)
    $ echo ~-
    /c/Users/Administrator/Desktop/github/git  

現在好了

變數擴充套件

這個大家最熟悉了,$真是個好東西,變數擴充套件,命令替換,算術擴充套件都離不了它(當然還能買東西)。一般情況下我們習慣使用$var,其實正規的格式是${var}。前一種形式更簡便,後一種更強大,很多時候必須用後一種形式才行。

先說間接引用,這東西很像C語言裡的指標

${!var} 就是在花括號後面緊跟一個感嘆號。bash會把變數的值作為新的變數再求值

      Administrator@AAA MINGW64 ~/Desktop/github/git (master)
      $ a=b
      Administrator@AAA MINGW64 ~/Desktop/github/git (master)
      $ b=1
      Administrator@AAA MINGW64 ~/Desktop/github/git (master)
      $ echo ${!a}
      1
  其他的變數操作,列表看到的更清晰
      形式                  意義
${var:-word}   如果變數var已被設定且非空,則代入它的值,否則帶入word
${var:=word}   如果變數var已被設定且空,就帶入它的值,否則將var設為word並帶入var,位置參量不能用這種方式賦值。
${var:+word}   如果var已被設定且值非空,帶入word,否則什麼都不帶入(帶入空)
${var:?word}   如果var已被設定且值非空,就帶入它的值,否則列印word並退出shell。省略word會輸出:parameter null or not set

注意:上面word可以是一個變數,使用$word的形式引用其值

${var:offset} 獲取var中offset開始的字串
${var:offset:length} 獲取var中offset開始長為length的字串。
注意:上面的offset和length可以使變數,使用offset,length引用其值

${#var} 替換為變數中字元個數,如果var是* ,@或陣列,長度則是位置參量
的個數。
${var%pattern} 把字串尾部與模式進行最小匹配,並刪除匹配到的部分。
${var%%pattern} 把字串尾部與模式進行最大匹配,並刪除匹配到的部分。
${var#pattern} 把字串頭部與模式進行最小匹配,並刪除匹配到的部分。
${var##pattern} 把字串頭部與模式進行最大匹配,並刪除匹配到的部分
${var/pattern/string} 使用string替換pattern的最大匹配部分。

如果pattern以/開頭則進行全部替換,否則只替換第一個匹配的位置。如果pattern以#開始,則起始部分必須匹配,如果以%開始則結尾部分必須匹配

注意
上面的pattern可以使變數,使用$pattern引用其值。
如果var是 、@ 或陣列,且以下標為 * 或 @ 的形式出現,則對其中每一個元素都進行匹配操作。

命令替換

用命令的輸出來替換命令本身。有兩種形式$(cmd)和cmd,推薦前一種形式,後一種形式是old-style了。

算術擴充套件

用算術表示式的值替換算術表示式本身。格式$((expr))。expr是個表示式,如4+3。理解起來比較簡單。不過關於expression,bash有自己特定的支援,某些運算它是做不了的。

 /c/Users/Administrator/Desktop/github/git
 $ echo $((9+2))   
  11  
 /c/Users/Administrator/Desktop/github/git
 $ b=2  
 /c/Users/Administrator/Desktop/github/git
 $ echo $((4+b))   
  6  

路徑擴充套件

shell掃描每個標記看看是否有 * ? [] 這三個就是進行路徑擴充套件的。
如果某個標記裡出現了三者中的一個或多個,這個標記就被認為是一個模式,

shell會對當前目錄下的檔案列表按檔名排序並逐一與此模式進行比較,如果有匹配這個模式的檔案,shell用所有能匹配這個模式的檔名列表替換這個模式。如果沒有能匹配這個模式的檔案,shell原樣保留該模式。

當然,shell提供了很多選項,定製匹配成功和失敗的處理,還可以選擇使用高階的正則表示式,這裡不進行討論,只說說shell的預設情況
此處的三個特殊字元也都比較簡單 * 匹配0到多個字元,?匹配一個字元,[]匹配某個去區間裡一個字元

相關推薦

shell 命令執行順序

shell 命令執行順序 shell執行命令的步驟順序如上圖,看起來有些複雜。 當命令列被處理時,每一個步驟都是在Shell的記憶體裡發生的;Shell不會真的把每個步驟的發生顯示給你看。 所以,你可以假想這事我們偷窺Shell記憶體裡的情況,從而知

shell命令執行順序

&&,||,(),{} 四個符號的運用shell指令碼執行命令的時候,有時候會依賴於前一個命令是否執行成功。而&&和||就是用來判斷前一個命令執行效果的。1  &&   使用方法:命令1 &&  命令2

LINUX 筆記-命令執行順序 && ,||

word 筆記 linu file ech bak 格式 說明 目錄 && 格式:命令1 && 命令2 說明:命令1返回真(即返回0,成功被執行)後,命令2才能夠被執行 例:/apps/bin目錄將會被移到/apps/dev/bin目錄下,如

Linux的系統呼叫 網路連線狀態 磁碟I/O 可疑行為監控/日誌收集 SHELL命令執行流程

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

命令執行順序控制與管道

通常情況下,我們每次只能在終端輸入一條命令,按下回車執行,執行完成後,我們再輸入第二條命令,然後再按回車執行……,當有時候我們會一次輸入多條命令,這個時候的執行過程又是如何的呢? 當我們需要使用apt-get安裝一個軟體,然後安裝完成後立即執行安裝的軟體(或命令

Linux shell命令解析器(),bash終端

環境: Ubuntu14-4   核心 4.4.0-135 vim編輯器 7.4  gcc  4.8.4  1.1 知識點 Shell 的基本概念 程序控制相關的系統呼叫的使用(如 fork,exec函式族) 整理框架: 1.命令直譯器首先是一個死迴圈。 2.

shell命令執行hive指令碼(hive互動,hive的shell程式設計)

Hive執行方式 Hive的hql命令執行方式有三種: 1、CLI 方式直接執行 2、作為字串通過shell呼叫hive –e執行(-S開啟靜默,去掉”OK”,”Time taken”) 3、作

7、linux命令執行順序控制與管道

cut,grep,wc,sort命令的使用 管道的理解 簡單的順序執行你可以使用;來完成,比如上述操作你可以: sudo apt-get update;sudo apt-get insatll some-tool;some-tool 結合&&am

linux下網路shell命令總結(

網路和監控命令類似於這些: hostname, ping, ifconfig, iwconfig, netstat, nslookup, traceroute, finger, telnet, ethtool 用於檢視 linux 伺服器 ip 地址,管理伺服器網路配置,通過 telnet

Linux:命令執行順序控制與管道

# 命令執行順序控制與管道 ## 順序執行 簡單的順序命令可以使用符號“;”完成,如:sudo apt-get update;sudo apt-get install

linux使用popen讀取shell命令執行結果

popen函式詳解 描述 popen() 函式 用 建立管道 的 方式 啟動 一個 程序, 並呼叫 shell. 因為 管道 是被定義成 單向的, 所以 type 引數 只能 定義成 只讀 或者 只寫, 不能是 兩者同時, 結果流 也相應的 是 只讀 或者 只寫.

python開發筆記--如何通過python程式碼進行shell命令執行

    話說又到了做學習筆記的時間,感覺現在做總結筆記已經成了我工作的一部分~    今天來說一下我們在python中如何去執行shell命令操作:(以前我竟然不知道,簡直不能太簡單了)    1.第一種方式:    import os    os.system('cd /U

linux命令執行順序管理

sleep 文件 done 命令 執行 管理 let grep color bi.sh文件內容如下: #!/bin/bash date1=$1 round=$2 if [ "$date1" == "" ];then date1=$(date "+%

SHELL指令碼攻略(學習筆記)--1.3 多命令邏輯執行順序

每條命令後如果不加&的話就是依次一行一行的順序執行,只有前面一行執行完成後再執行下一行,事實上還有很多特殊符號可用來分隔單個的命令:分號(;)、管道(|)、&、邏輯AND (&&),還有邏輯OR (||)。對於每一個讀取的管道,Shell都回

Shell指令碼命令執行順序

如果希望在成功地執行一個命令之後再執行另一個命令,或者在一個命令失敗後再執行另一個命令,&&和||可以完成這樣的功能。相應的命令可以是系統命令或shell指令碼。Shell還提供了在當前shell或子shell中執行一組命令的方法,即使用()和{}。 1.使用&&: 形式:命令

利用shell指令碼執行ssh遠端另臺主機執行命令並返回命令的結果集

假設從主機A,檢查主機B上的程序, 需要在主機B上建立檢查使用者,例如叫x, 並設定通過public key認證登入SSH,不會可以google搜一下, 然後,在A機器上執行: ssh [email protected] ~/command.sh > re

shell指令碼不暫停程序,暫停幾秒執行shell命令

需求如下: 跑monkey指令碼如果遇到異常結束,則使用logcat輸出日誌,輸出三秒後停止輸出 如果使用sleep 命令的話,則會導致logcat在sleep的時候也暫停執行了 解決方法如下,通過while迴圈暫停3秒: ti1=`date +%s` #獲取時間戳

shell指令碼中順序執行另幾條shell命令

命令執行操作符 多條命令可以在一行中出現。它們可以從左到右順序執行。此時,各條命令之間應以分號( ;)隔開. 如:    pwd ; who | wc -l ; cd /usr/bin 在相鄰命令間可存在邏輯關係,即邏輯“與”和邏輯“或”。 邏輯與操作符“&&

Centos 執行shell命令返回127錯誤

建數據庫 mysq data 存在 思路 功能 自動創建 運行 用戶 shell腳本功能:連接mysql,自動創建數據庫,腳本如下 mysql -h$MYSQL_IP -u$MYSQL_USER -p$MYSQL_PASSWORD --default-character-s

php 執行shell命令 打印錯誤信息

信息 資源 null function $cmd = "rm 1.txt";//刪除一個不存在的文件,查看報錯信息 $res = doShell($cmd); var_dump($res); //該函數沒有限制條件,可以直接放在代碼中使用 function doShell($cmd,$cwd=