首頁 > 軟體

Shell變數、資料重定向和管道

2020-06-16 17:33:15

在上一篇部落格Shell功能、設定和外掛中,介紹了為什麼要使用shell,shell有哪些功能,如何使用oh my zsh來提高效率等,本篇重點介紹,shell中的變數的如何設定和讀取資料,讀取之後如何使用變數?每個程式一般都有輸入和輸出,讓我們看看資料重定向如何處理輸入和輸出的?還有,Unix/Linux系統提供豐富的工具,我們如何將這些工具通過管道來組合成更加強大的宏工具呢?下面,由我來逐一詳細介紹變數、資料重定向和管道。


Variable & Redirection & Pipe.png

變數

變數的作用

變數與其他程式設計語言一樣,都是儲存資料,然後被程式參照。相比於不使用變數,而是直接使用資料,存在兩個問題:

  1. 當資料改變時,直接使用資料的時候卻不能靈活地根據資料改變而隨著改變,而使用變數卻不同,它能夠做到這點。
  2. 當資料發生變化時,如果想保證資料一致性,必須查詢所有參照該資料的所有地方,然後將它修改,當下一次再需要修改時,也是像這種情況一樣,是多麼繁瑣的事,而變數卻不用,只需要修改變數值即可。

因此,變數具有可變性易於修改的兩個特點。

變數的分類

在shell中,大概分為兩種變數:環境變數區域性變數,主要區別在於它們的使用範圍不同,環境變數可以在父進程與子進程之間共用,而自定義變數只在本進程使用。舉一個簡單的例子來說明:


no share variable.png

我首先設定一個shell變數devname=sam,然後輸入bash開啟一個新的shell,而這個shell是子進程,然後echo $devname輸出變數值,變數值為空,最後exit退出子進程。


share variable.png

但使用export devname設定環境變數後,再次進入輸入bash進入子進程之後,echo $devname輸出變數值,這次變數值是sam

檢視環境變數envset

如果想檢視系統中以及自定義有哪些環境變數,可以使用env命令:


env command.png

set命令不僅能檢視環境變數,還可以檢視與shell介面有關的變數,下面只擷取一部分變數:


set command.png

變數有哪些操作

顯示echo $variable

如果你想顯示某個變數的值,例如PATH,你只需要輸入:

echo $PATH

echo command.png

注意上面一條命令,需要在變數名前加上一個符號$,這樣才能存取變數

設定variable=value和取消unset

如果你想設定某個變數的值,只需在變數名和變數值之間用符號=連線就行了,例如:


set variable.png

由上面的輸入命令echo $devname,顯示結果為。由此可知,一開始如果沒有設定某個變數時,它的是為。另外,設定變數的規則還需要幾點注意:

  1. 在命名變數名時,變數名稱只能是英文字母和數位,而且首字母不能是數位。下面演示一個錯誤的例子:


    wrong variable name.png
  2. 等號=兩邊不能有空格


    blank can't exist.png
  3. 如果變數值有空格,可用雙引號" "或單引號' '來包圍變數值,但兩者是有區別:
    雙引號" "內的一些特殊字元,可以保持原有的特性,例如:


    double quotation marks.png

    而單引號' '內的一些特殊字元,僅為一般字元,即純文字,例如:


    single quotation marks.png
  4. 如果想顯示一些特殊字元($、空格、!等),在字元前面加上用跳脫字元

  5. 有些時候,變數的值可能來源於一些命令,這時你可以使用反單引號`命令`$(命令),例如:
    使用反單引號`命令`的方式


    get information from comand 1.png

    使用$(命令)的方式


    get information from comand 2.png
  6. 如果變數想增加變數的值,可以使用$variable累加


    append variable value.png
  7. 如果變數需要在其他子進程使用,用export關鍵字來設定變數為環境變數

    export VARIABLE
  8. 系統環境變數一般都是字母全部大寫,例如:PATHHOMESHELL

  9. 如果想取消設定變數的值,使用unset variable命令。注意,變數之前是沒有符號$


    unset variable.png

環境組態檔

之前那些設定的環境變數,一旦退出系統後,就不能再次使用,如果想再次使用,必須重新再設定才行。如果想就算退出系統,也能重新使用自定義的環境變數,那怎麼辦呢?

不用怕,系統提供一些環境組態檔:/etc/profile~/.bash_profile/etc/profile是系統整體的設定,每個使用者共用,最好不要修改;而~/.bash_profile屬於單個使用者的設定,每個使用者設定後,互不影響和共用。但因為我使用oh my zsh,之前~/.bash_profile設定一些設定都不生效了,但它提供一個環境組態檔.zshrc,所以如果想設定環境變數TEST,只需將export TEST=test新增.zshrc即可。


export variable in zshrc file.png

但在.zshrc檔案設定好環境變數TEST後,echo $TEST為空,原因是還沒使用source命令來讀取環境組態檔。使用source .zshrc命令之後,設定環境變???TEST生效了


source command.png

資料重定向

含義

當輸入命令列時,一般都有輸入引數(standard input),而命令列處理完之後,一般都有輸出結果,結果有可能成功(standard output),也有可能失敗(standard error),而這些結果一般都會輸出到螢幕上,如果你想控制結果輸出到檔案或以檔案作為輸入的話,你需要了解資料重定向的分類和符號操作。


Redirection.png

分類

資料重定向主要分為三類:

  • stdin,表示標準輸入,程式碼為0,使用<<<操作符
    符號<表示以檔案內容作為輸入
    符號<<表示輸入時的結束符號
  • stdout,表示標準輸出,程式碼為1,使用>>>操作符
    符號>表示以覆蓋的方式將正確的資料輸出到指定檔案中
    符號>>表示以追加的方式將正確的資料輸出到指定檔案中
  • stderr,表示標準錯誤輸出,程式碼為2,使用2>2>>操作符
    符號2>表示以覆蓋的方式將錯誤的資料輸出到指定檔案中
    符號2>>表示以追加的方式將錯誤的資料輸出到指定檔案中

使用

stdout

當你輸入ls命令,螢幕會顯示當前目錄有哪些檔案和目錄;而當你使用符號>時,輸出結果將重定向到dir.txt檔案,而不顯示在螢幕上


stdin demo.png

而符號>與符號>>有什麼區別呢?>表示當檔案存在時,將檔案內容清空,然後stdout結果存放到檔案中。而>>表示當檔案存在時,檔案內容並沒有清空,而是將stdout結果追加到檔案尾部。

當你再次輸入命令ls > dir.txt時,檔案內容並沒有改變,因為之前檔案內容被清空,然後stdout結果存放在dir.txt檔案


stdin demo 1.png

而你這次使用符號ls >> dir.txt的話,檔案內容被追加到dir.txt檔案


stdin demo 2.png
stderr

這次我輸入命令ls test顯示一個不存在的檔案,會顯示錯誤資訊。然後將錯誤資訊輸出到檔案error.txt


stderr demo 1.png

如果你想追加錯誤資訊,可以使用2>>符號


stderr demo 2.png
stdout & stderr
  • 將stdout和stderr分離:>2>符號
    輸入ls README.md test,在螢幕顯示既有正確資訊,也有錯誤資訊,如果想將正確資訊和錯誤資訊分離到不同檔案,你可以同時使用>2>符號


    seperate stdout & stderr.png
  • 將stdout和stderr合併:&>符號
    如果你想將正確資訊和錯誤資訊合併,且輸出到同一個檔案,可以使用&>符號


    combine stdout & stderr.png
stdin

一般輸入一些簡單的資料的方式都是通過鍵盤,但是如果要輸入大量的資料,最好還是通過檔案的方式。舉一個簡單例子:
首先輸入cat > test命令之後,你就可以輸入內容,那些內容最終會存放在test檔案


stdin demo 1.png

但如果有大量資料從一個檔案匯入到test檔案時,此時需要用到<符號


stdin demo 2.png

還一個符號<<需要解釋,符號<<表示輸入時的結束符號。輸入cat > test << "eof"命令之後,你就可以輸入內容,那些內容最終會存放在test檔案,輸入完內容後可以輸入eof來結束輸入


stdin demo 3.png

管道

在Unix設計哲學中,有一個重要設計原則--KISS(Keep it Simple, Stupid),大概意思就是只關注如何做好一件事,並把它做到極致。每個程式都有各自的功能,那麼有沒有一樣東西將不同功能的程式互相連通,自由組合成更為強大的宏工具呢?此時,管道出現了,它能夠讓程式實現了高內聚,低耦合


How Pipe works.png

如果我想檢視檔案是否存在某個關鍵字,此時我可以使用管道


Pipe Demo.png

命令cat README.md | grep 'pod'的處理過程分為兩步:

  1. cat README.md檢視檔案內容
  2. 然後將cat README.md輸出的內容作為grep 'pod'命令的輸入,再進行處理。

上面一個很關鍵的符號|,就是管道,它能夠將前一個命令處理完的stdout作為下一條命令stdin

本文永久更新連結地址http://www.linuxidc.com/Linux/2016-09/135156.htm


IT145.com E-mail:sddin#qq.com