2021-05-12 14:32:11
Shell變數、資料重定向和管道
在上一篇部落格Shell功能、設定和外掛中,介紹了為什麼要使用shell,shell有哪些功能,如何使用oh my zsh來提高效率等,本篇重點介紹,shell中的變數的如何設定和讀取資料,讀取之後如何使用變數?每個程式一般都有輸入和輸出,讓我們看看資料重定向如何處理輸入和輸出的?還有,Unix/Linux系統提供豐富的工具,我們如何將這些工具通過管道來組合成更加強大的宏工具呢?下面,由我來逐一詳細介紹變數、資料重定向和管道。
變數
變數的作用
變數與其他程式設計語言一樣,都是儲存資料,然後被程式參照。相比於不使用變數,而是直接使用資料,存在兩個問題:
- 當資料改變時,直接使用資料的時候卻不能靈活地根據資料改變而隨著改變,而使用變數卻不同,它能夠做到這點。
- 當資料發生變化時,如果想保證資料一致性,必須查詢所有參照該資料的所有地方,然後將它修改,當下一次再需要修改時,也是像這種情況一樣,是多麼繁瑣的事,而變數卻不用,只需要修改變數值即可。
因此,變數具有可變性和易於修改的兩個特點。
變數的分類
在shell中,大概分為兩種變數:環境變數和區域性變數,主要區別在於它們的使用範圍不同,環境變數可以在父進程與子進程之間共用,而自定義變數只在本進程使用。舉一個簡單的例子來說明:
我首先設定一個shell變數devname=sam
,然後輸入bash
開啟一個新的shell,而這個shell是子進程,然後echo $devname
輸出變數值,變數值為空,最後exit
退出子進程。
但使用export devname
設定環境變數後,再次進入輸入bash
進入子進程之後,echo $devname
輸出變數值,這次變數值是sam
檢視環境變數env
和set
如果想檢視系統中以及自定義有哪些環境變數,可以使用env
命令:
而set
命令不僅能檢視環境變數,還可以檢視與shell介面有關的變數,下面只擷取一部分變數:
變數有哪些操作
顯示echo $variable
如果你想顯示某個變數的值,例如PATH
,你只需要輸入:
echo $PATH
注意上面一條命令,需要在變數名前加上一個符號$
,這樣才能存取變數
設定variable=value
和取消unset
如果你想設定某個變數的值,只需在變數名和變數值之間用符號=
連線就行了,例如:
由上面的輸入命令echo $devname
,顯示結果為空。由此可知,一開始如果沒有設定某個變數時,它的是為空。另外,設定變數的規則還需要幾點注意:
-
在命名變數名時,變數名稱只能是英文字母和數位,而且首字母不能是數位。下面演示一個錯誤的例子:
-
等號
=
兩邊不能有空格
-
如果變數值有空格,可用雙引號
" "
或單引號' '
來包圍變數值,但兩者是有區別:
雙引號" "
內的一些特殊字元,可以保持原有的特性,例如:
而單引號
' '
內的一些特殊字元,僅為一般字元,即純文字,例如:
-
如果想顯示一些特殊字元($、空格、!等),在字元前面加上用跳脫字元
-
有些時候,變數的值可能來源於一些命令,這時你可以使用反單引號
`
命令`
或$(命令)
,例如:
使用反單引號`
命令`
的方式
使用
$(命令)
的方式
-
如果變數想增加變數的值,可以使用
$variable
累加
-
如果變數需要在其他子進程使用,用
export
關鍵字來設定變數為環境變數export VARIABLE
-
系統環境變數一般都是字母全部大寫,例如:
PATH
,HOME
,SHELL
等 -
如果想取消設定變數的值,使用
unset variable
命令。注意,變數之前是沒有符號$
環境組態檔
之前那些設定的環境變數,一旦退出系統後,就不能再次使用,如果想再次使用,必須重新再設定才行。如果想就算退出系統,也能重新使用自定義的環境變數,那怎麼辦呢?
不用怕,系統提供一些環境組態檔:/etc/profile
和~/.bash_profile
。/etc/profile
是系統整體的設定,每個使用者共用,最好不要修改;而~/.bash_profile
屬於單個使用者的設定,每個使用者設定後,互不影響和共用。但因為我使用oh my zsh,之前~/.bash_profile
設定一些設定都不生效了,但它提供一個環境組態檔.zshrc
,所以如果想設定環境變數TEST,只需將export TEST=test
新增.zshrc
即可。
但在.zshrc
檔案設定好環境變數TEST
後,echo $TEST
為空,原因是還沒使用source
命令來讀取環境組態檔。使用source .zshrc
命令之後,設定環境變???TEST
生效了
資料重定向
含義
當輸入命令列時,一般都有輸入引數(standard input),而命令列處理完之後,一般都有輸出結果,結果有可能成功(standard output),也有可能失敗(standard error),而這些結果一般都會輸出到螢幕上,如果你想控制結果輸出到檔案或以檔案作為輸入的話,你需要了解資料重定向的分類和符號操作。
分類
資料重定向主要分為三類:
stdin
,表示標準輸入,程式碼為0,使用<
或<<
操作符
符號<
表示以檔案內容作為輸入
符號<<
表示輸入時的結束符號stdout
,表示標準輸出,程式碼為1,使用>
或>>
操作符
符號>
表示以覆蓋的方式將正確的資料輸出到指定檔案中
符號>>
表示以追加的方式將正確的資料輸出到指定檔案中stderr
,表示標準錯誤輸出,程式碼為2,使用2>
或2>>
操作符
符號2>
表示以覆蓋的方式將錯誤的資料輸出到指定檔案中
符號2>>
表示以追加的方式將錯誤的資料輸出到指定檔案中
使用
stdout
當你輸入ls
命令,螢幕會顯示當前目錄有哪些檔案和目錄;而當你使用符號>
時,輸出結果將重定向到dir.txt
檔案,而不顯示在螢幕上
而符號>
與符號>>
有什麼區別呢?>
表示當檔案存在時,將檔案內容清空,然後stdout結果存放到檔案中。而>>
表示當檔案存在時,檔案內容並沒有清空,而是將stdout結果追加到檔案尾部。
當你再次輸入命令ls > dir.txt
時,檔案內容並沒有改變,因為之前檔案內容被清空,然後stdout結果存放在dir.txt
檔案
而你這次使用符號ls >> dir.txt
的話,檔案內容被追加到dir.txt
檔案
stderr
這次我輸入命令ls test
顯示一個不存在的檔案,會顯示錯誤資訊。然後將錯誤資訊輸出到檔案error.txt
。
如果你想追加錯誤資訊,可以使用2>>
符號
stdout & stderr
-
將stdout和stderr分離:
>
和2>
符號
輸入ls README.md test
,在螢幕顯示既有正確資訊,也有錯誤資訊,如果想將正確資訊和錯誤資訊分離到不同檔案,你可以同時使用>
和2>
符號
-
將stdout和stderr合併:
&>
符號
如果你想將正確資訊和錯誤資訊合併,且輸出到同一個檔案,可以使用&>
符號
stdin
一般輸入一些簡單的資料的方式都是通過鍵盤,但是如果要輸入大量的資料,最好還是通過檔案的方式。舉一個簡單例子:
首先輸入cat > test
命令之後,你就可以輸入內容,那些內容最終會存放在test
檔案
但如果有大量資料從一個檔案匯入到test
檔案時,此時需要用到<
符號
還一個符號<<
需要解釋,符號<<
表示輸入時的結束符號。輸入cat > test << "eof"
命令之後,你就可以輸入內容,那些內容最終會存放在test
檔案,輸入完內容後可以輸入eof
來結束輸入
管道
在Unix設計哲學中,有一個重要設計原則--KISS(Keep it Simple, Stupid),大概意思就是只關注如何做好一件事,並把它做到極致。每個程式都有各自的功能,那麼有沒有一樣東西將不同功能的程式互相連通,自由組合成更為強大的宏工具呢?此時,管道出現了,它能夠讓程式實現了高內聚,低耦合。
如果我想檢視檔案是否存在某個關鍵字,此時我可以使用管道
命令cat README.md | grep 'pod'
的處理過程分為兩步:
cat README.md
檢視檔案內容- 然後將
cat README.md
輸出的內容作為grep 'pod'
命令的輸入,再進行處理。
上面一個很關鍵的符號|
,就是管道,它能夠將前一個命令處理完的stdout
作為下一條命令stdin
。
本文永久更新連結地址:http://www.linuxidc.com/Linux/2016-09/135156.htm
相關文章