在上一篇博客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>>
表示以追加的方式將錯誤的數據輸出到指定文件中當你輸入ls
命令,屏幕會顯示當前目錄有哪些文件和目錄;而當你使用符號>
時,輸出結果將重定向到dir.txt
文件,而不顯示在屏幕上
而符號>
與符號>>
有什麼區別呢?>
表示當文件存在時,將文件內容清空,然後stdout結果存放到文件中。而>>
表示當文件存在時,文件內容並沒有清空,而是將stdout結果追加到文件尾部。
當你再次輸入命令ls > dir.txt
時,文件內容並沒有改變,因為之前文件內容被清空,然後stdout結果存放在dir.txt
文件
而你這次使用符號ls >> dir.txt
的話,文件內容被追加到dir.txt
文件
這次我輸入命令ls test
顯示一個不存在的文件,會顯示錯誤信息。然後將錯誤信息輸出到文件error.txt
。
如果你想追加錯誤信息,可以使用2>>
符號
將stdout和stderr分離:>
和2>
符號
輸入ls README.md test
,在屏幕顯示既有正確信息,也有錯誤信息,如果想將正確信息和錯誤信息分離到不同文件,你可以同時使用>
和2>
符號
將stdout和stderr合並:&>
符號
如果你想將正確信息和錯誤信息合並,且輸出到同一個文件,可以使用&>
符號
一般輸入一些簡單的數據的方式都是通過鍵盤,但是如果要輸入大量的數據,最好還是通過文件的方式。舉一個簡單例子:
首先輸入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
。