在上一篇博客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。