shell的變量

概要:

         shell中,變量有環境變量和自定義變量之分,環境 變量相當於全局變量,自定義變量相當於局部變量,因此父程序的環境變量變量會被子程序所引用,而自定義變量則不可以。其中的原因在於子程序僅會繼承父程序的環境變量, 子程序不會繼承父程序的自定義變量。

  1. 爲什麼環境變量的數據可以被子程序所引用呢?這是因爲內存配置的關係!理論上是這樣的: 
  2.  
  3. 當啓動一個 shell,操作系統會分配一記憶區塊給 shell 使用,此內存內之變量可讓子程序取用 
  4. 若在父程序利用 export 功能,可以讓自定義變量的內容寫到上述的記憶區塊當中(環境變量); 
  5. 當加載另一個 shell 時 (亦即啓動子程序,而離開原本的父程序了),子 shell 可以將父 shell 的環境變量所在的記憶區塊導入自己的環境變量區塊當中。 
  1. 本文目錄索引: 
  2. 1、變量的顯示 
  3.                   echo --顯示變量內容 
  4.                   unset --取消變量 
  5.                   env --觀察環境變量 
  6.                   set --觀察環境變量與自定義變量 
  7.                  export --自定義變量轉成環境變量 
  8.                  declare / typeset --宣告變量的類型(也可以將環境變量轉成自定義變量) 
  9. 2、變量的讀取 
  10.                  read --讀取來自鍵盤輸入的變量 
  11. 3、通配符與特殊符號 
  12. 4、變量的配置守則 
  13. 5、變量內容的刪除、取代與測試、替換 
  14.                變量內容的刪除與取代 刪除 取代
  15. 變量的測試與內容替換 

變量的顯示


 echo --顯示變量內容
  1. 格式:echo $variable  
  2.           echo ${variable}  
  1.  echo $PATH 
  2. /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin 
  3. [root@www ~]# echo ${PATH} 
  4. /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin 

 unset --取消變量
  1. 格式:unset 變量名稱 
  1. 取消 myname 的配置:  
  2. [root@www ~]#unset myname  

 env --觀察環境變量
  1. 範例一:列出目前的 shell 環境下的所有環境變量與其內容。 
  2. [root@www ~]# env 
  3. HOSTNAME=www.vbird.tsai    <== 這部主機的主機名 
  4. TERM=xterm                 <== 這個終端機使用的環境是什麼類型 
  5. SHELL=/bin/bash            <== 目前這個環境下,使用的 Shell 是哪一個程序? 
  6. HISTSIZE=1000              <== 『記錄命令的筆數』在 CentOS 默認可記錄 1000 筆 
  7. USER=root                  <== 使用者的名稱啊! 
  8. LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01: 
  9. or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0 
  10. 0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz= 
  11. 00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3 
  12. 1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00 
  13. ;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些顏色顯示 
  14. MAIL=/var/spool/mail/root  <== 這個用戶所取用的 mailbox 位置 
  15. PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin: 
  16. /root/bin                  <== 不再多講啊!是運行文件命令搜尋路徑 
  17. INPUTRC=/etc/inputrc       <== 與鍵盤按鍵功能有關。可以配置特殊按鍵! 
  18. PWD=/root                  <== 目前用戶所在的工作目錄 (利用 pwd 取出!) 
  19. LANG=en_US                 <== 這個與語系有關,底下會再介紹! 
  20. HOME=/root                 <== 這個用戶的家目錄啊! 
  21. _=/bin/env                 <== 上一次使用的命令的最後一個參數(或命令本身) 

部分環境變量的介紹如下:

  1. HOME 
  2. 代表用戶的家目錄。還記得我們可以使用 cd ~ 去到自己的家目錄嗎?或者利用 cd 就可以直接回到用戶家目錄了。那就是取用這個變量啦~ 有很多程序都可能會取用到這個變量的值! 
  3.  
  4. SHELL 
  5. 告知我們,目前這個環境使用的 SHELL 是哪支程序? Linux 默認使用 /bin/bash 的啦! 
  6.  
  7. HISTSIZE 
  8. 這個與『歷史命令』有關,亦即是, 我們曾經下達過的命令可以被系統記錄下來,而記錄的『筆數』則是由這個值來配置的。 
  9.  
  10. MAIL 
  11. 當我們使用 mail 這個命令在收信時,系統會去讀取的郵件信箱文件 (mailbox)。 
  12.  
  13. PATH 
  14. 就是運行文件搜尋的路徑啦~目錄與目錄中間以冒號(:)分隔, 由於文件的搜尋是依序由 PATH 的變量內的目錄來查詢,所以,目錄的順序也是重要的喔。 
  15.  
  16. LANG 
  17. 這個重要!就是語系數據囉~很多信息都會用到他, 舉例來說,當我們在啓動某些 perl 的程序語言文件時,他會主動的去分析語系數據文件, 如果發現有他無法解析的編碼語系,可能會產生錯誤喔!一般來說,我們中文編碼通常是 zh_TW.Big5 或者是 zh_TW.UTF-8,這兩個編碼偏偏不容易被解譯出來,所以,有的時候,可能需要修訂一下語系數據。 這部分我們會在下個小節做介紹的! 
  18.  
  19. RANDOM 
  20. 這個玩意兒就是『隨機隨機數』的變量啦!目前大多數的 distributions 都會有隨機數生成器,那就是 /dev/random 這個文件。 我們可以透過這個隨機數文件相關的變量 ($RANDOM) 來隨機取得隨機數值喔。在 BASH 的環境下,這個 RANDOM 變量的內容,介於 0~32767 之間,所以,你只要 echo $RANDOM 時,系統就會主動的隨機取出一個介於 0~32767 的數值。萬一我想要使用 0~9 之間的數值呢?呵呵~利用 declare 宣告數值類型, 然後這樣做就可以了: 
  21. [root@www ~]# declare -i number=$RANDOM*10/32768  
  22. [root@www ~]#  echo $number 
  23. 8   <== 此時會隨機取出 0~9 之間的數值喔! 
 

 set --觀察環境變量與自定義變量
  1. 一般來說,不論是否爲環境變量,只要跟我們目前這個 shell 的操作接口有關的變量, 通常都會被配置爲大寫字符,也就是說,『基本上,在 Linux 默認的情況中,使用{大寫的字母}來配置的變量一般爲系統內定需要的變量』。 OK!OK!那麼上頭那些變量當中,有哪些是比較重要的?大概有這幾個吧! 
  2.  
  3.  
  4.  
  5. PS1:(提示字符的配置) 
  6.  
  7. 這是 PS1 (數字的 1 不是英文字母),這個東西就是我們的『命令提示字符』喔! 當我們每次按下 [Enter] 按鍵去運行某個命令後,最後要再次出現提示字符時, 就會主動去讀取這個變量值了。上頭 PS1 內顯示的是一些特殊符號,這些特殊符號可以顯示不同的信息, 每個 distributions 的 bash 默認的 PS1 變量內容可能有些許的差異,不要緊,『習慣你自己的習慣』就好了。 你可以用 man bash (注3)去查詢一下 PS1 的相關說明,以理解底下的一些符號意義。 
  8.  
  9. \d :可顯示出『星期 月 日』的日期格式,如:"Mon Feb 2" 
  10. \H :完整的主機名。舉例來說,鳥哥的練習機爲『www.vbird.tsai』 
  11. \h :僅取主機名在第一個小數點之前的名字,如鳥哥主機則爲『www』後面省略 
  12. \t :顯示時間,爲 24 小時格式的『HH:MM:SS』 
  13. \T :顯示時間,爲 12 小時格式的『HH:MM:SS』 
  14. \A :顯示時間,爲 24 小時格式的『HH:MM』 
  15. \@ :顯示時間,爲 12 小時格式的『am/pm』樣式 
  16. \u :目前使用者的賬號名稱,如『root』; 
  17. \v :BASH 的版本信息,如鳥哥的測試主板本爲 3.2.25(1),僅取『3.2』顯示 
  18. \w :完整的工作目錄名稱,由根目錄寫起的目錄名稱。但家目錄會以 ~ 取代; 
  19. \W :利用 basename 函數取得工作目錄名稱,所以僅會列出最後一個目錄名。 
  20. \# :下達的第幾個命令。 
  21. \$ :提示字符,如果是 root 時,提示字符爲 # ,否則就是 $ 囉~ 
  22.  
  23. 好了,讓我們來看看 CentOS 默認的 PS1 內容吧:『[\u@\h \W]\$ 』,現在你知道那些反斜槓後的數據意義了吧? 要注意喔!那個反斜槓後的數據爲 PS1 的特殊功能,與 bash 的變量配置沒關係啦!不要搞混了喔! 那你現在知道爲何你的命令提示字符是:『 [root@www ~]# 』了吧? 好了,那麼假設我想要有類似底下的提示字符: 
  24. [root@www /home/dmtsai 16:50 #12]# 
  25. 那個 # 代表第 12 次下達的命令。那麼應該如何配置 PS1 呢?可以這樣啊: 
  26. [root@www ~ ]# cd /home 
  27. [root@www home]# PS1='[\u@\h \w \A #\#]\$ ' 
  28. [root@www /home 17:02 #85]#  
  29. # 看到了嗎?提示字符變了!變的很有趣吧!其中,那個 #85 比較有趣, 
  30. # 如果您再隨便輸入幾次 ls 後,該數字就會添加喔!爲啥?上面有說明滴! 
  31.  
  32.  
  33.  
  34. $:(關於本 shell 的 PID) 
  35.  
  36. 錢字號本身也是個變量喔!這個咚咚代表的是『目前這個 Shell 的線程代號』,亦即是所謂的 PID (Process ID)。 更多的程序觀念,我們會在第四篇的時候提及。想要知道我們的 shell 的 PID ,就可以用:『 echo $$ 』即可!出現的數字就是你的 PID 號碼。 
  37.  
  38.  
  39.  
  40. ?:(關於上個運行命令的回傳值) 
  41.  
  42. 什麼?問號也是一個特殊的變量?沒錯!在 bash 裏面這個變量可重要的很! 這個變量是:『上一個運行的命令所回傳的值』, 上面這句話的重點是『上一個命令』與『回傳值』兩個地方。當我們運行某些命令時, 這些命令都會回傳一個運行後的代碼。一般來說,如果成功的運行該命令, 則會回傳一個 0 值,如果運行過程發生錯誤,就會回傳『錯誤代碼』纔對!一般就是以非爲 0 的數值來取代。 我們以底下的例子來看看: 
  43. [root@www ~]# echo $SHELL 
  44. /bin/bash                                  <==可順利顯示!沒有錯誤! 
  45. [root@www ~]# echo $? 
  46. 0                                          <==因爲沒問題,所以回傳值爲 0 
  47. [root@www ~]# 12name=VBird 
  48. -bash: 12name=VBird: command not found     <==發生錯誤了!bash回報有問題 
  49. [root@www ~]# echo $? 
  50. 127                                        <==因爲有問題,回傳錯誤代碼(非爲0) 
  51. # 錯誤代碼回傳值依據軟件而有不同,我們可以利用這個代碼來搜尋錯誤的原因喔! 
  52. [root@www ~]# echo $? 
  53. # 咦!怎麼又變成正確了?這是因爲 "?" 只與『上一個運行命令』有關, 
  54. # 所以,我們上一個命令是運行『 echo $? 』,當然沒有錯誤,所以是 0 沒錯! 
  55.  
  56.  
  57.  
  58. OSTYPE, HOSTTYPE, MACHTYPE:(主機硬件與核心的等級) 
  59.  
  60. 我們在第零章、計算器概論內的 CPU 等級說明中談過 CPU , 目前個人計算機的 CPU 主要分爲 32/64 位,其中 32 位又可分爲 i386, i586, i686,而 64 位則稱爲 x86_64。 由於不同等級的 CPU 命令集不太相同,因此你的軟件可能會針對某些 CPU 進行優化,以求取較佳的軟件性能。 所以軟件就有 i386, i686 及 x86_64 之分。以目前 (2009) 的主流硬件來說,幾乎都是 x86_64 的天下! 但是畢竟舊機器還是非常多,以鳥哥的環境來說,我用 P-III 等級的計算機,所以上頭就發現我的等級是 i686 啦! 
  61.  
  62. 要留意的是,較高階的硬件通常會向下兼容舊有的軟件,但較高階的軟件可能無法在舊機器上面安裝! 我們在第三章就曾說明過, 這裏再強調一次,你可以在 x86_64 的硬件上安裝 i386 的 Linux 操作系統,但是你無法在 i686 的硬件上安裝 x86_64 的 Linux 操作系統!這點得要牢記在心! 
 
 export --自定義變量轉成環境變量

 export可以將自定義變量變成環境變量,讓該變量值繼續存在於子程序,讓該變量內容繼續的在子程序中使用。

  1. 格式:export 變量名稱 

如果僅下達 export 而沒有接變量時,那麼此時將會把所有的『環境變量』顯示出來!例如:

  1. [root@www ~]# export 
  2. declare -x HISTSIZE="1000" 
  3. declare -x HOME="/root" 
  4. declare -x HOSTNAME="www.vbird.tsai" 
  5. declare -x INPUTRC="/etc/inputrc" 
  6. declare -x LANG="en_US" 
  7. declare -x LOGNAME="root" 
  declare / typeset --宣告變量的類型(也可以將環境變量轉成自定義變量)

 declare 語法如下:

如果你不小心將變量配置爲『只讀』,通常得要註銷再登陸才能復原該變量的類型了!

在默認的情況底下, bash 對於變量有幾個基本的定義:

  1. 變量類型默認爲『字符串』,所以若不指定變量類型,則 1+2 爲一個『字符串』而不是『計算式』。 所以上述第一個運行的結果纔會出現那個情況的; 
  2. bash 環境中的數值運算,默認最多僅能到達整數形態,所以 1/3 結果是 0; 

變量的讀取


 read --讀取來自鍵盤輸入的變量

 通配符與特殊符號


 

 變量的配置守則


  1. 1.變量名稱只能是英文字母與數字,但是開頭字符不能是數字,如下爲錯誤:   
  2. 『2myname=VBird』  
  3.   
  4. 2.等號兩邊不能直接接空格符,如下所示爲錯誤:   
  5. 『myname = VBird』或『myname=VBird Tsai』  
  6.   
  7. 3.變量內容若有空格符可使用雙引號『"』或單引號『'』將變量內容結合起來,但  
  8. 雙引號內的特殊字符如 $ 等,可以保有原本的特性,如下所示:  
  9. 『var="lang is $LANG"』則『echo $var』可得『lang is en_US』  
  10. 單引號內的特殊字符則僅爲一般字符 (純文本),如下所示:  
  11. 『var='lang is $LANG'』則『echo $var』可得『lang is $LANG』  
  12.   
  13. 4.在一串命令中,還需要藉由其他的命令提供的信息,可以使用反單引號『`命令`』或 『$(命令)』。特別注意,那個 ` 是鍵盤上方的數字鍵 1 左邊那個按鍵,而不是單引號! 例如想要取得核心版本的配置:  
  14. 『version=$(uname -r)』再『echo $version』可得『2.6.18-128.el5』  
  15.   
  16. 5.可用跳脫字符『 \ 』將特殊符號(如 [Enter], $, \, 空格符, '等)變成一般字符;  
  17.   
  18. 6.若該變量爲擴增變量內容時,則可用 "$變量名稱" 或 ${變量} 累加內容,如下所示:  
  19. 『PATH="$PATH":/home/bin』  
  20.   
  21. 7.通常大寫字符爲系統默認變量,自行配置變量可以使用小寫字符,方便判斷 (純粹依照使用者興趣與嗜好) ;  
  22.   
  23. 8.若該變量需要在其他子程序運行,則需要以 export 來使變量變成環境變量:  
  24. 『export PATH』  

舉例如下:

根據上面的案例你可以試試看!就可以瞭解變量的配置囉!這個是很重要的呦!請勤加練習! 其中,較爲重要的一些特殊符號的使用囉!例如單引號、雙引號、跳脫字符、錢字號、反單引號等等,底下的例題想一想吧!例題:

例題:
在變量的配置當中,單引號與雙引號的用途有何不同?
答:
單引號與雙引號的最大不同在於雙引號仍然可以保有變量的內容,但單引號內僅能是一般字符 ,而不會有特殊符號。我們以底下的例子做說明:假設您定義了一個變量, name=VBird ,現在想以 name 這個變量的內容定義出 myname 顯示 VBird its me 這個內容,要如何訂定呢?
[root@www ~]# name=VBird
[root@www ~]# echo $name
VBird
[root@www ~]# myname="$name its me"
[root@www ~]# echo $myname
VBird its me
[root@www ~]# myname='$name its me'
[root@www ~]# echo $myname
$name its me
發現了嗎?沒錯!使用了單引號的時候,那麼 $name 將失去原有的變量內容,僅爲一般字符的顯示型態而已!這裏必需要特別小心在意!

例題:
在命令下達的過程中,反單引號( ` )這個符號代表的意義爲何?
答:
在一串命令中,在 ` 之內的命令將會被先運行,而其運行出來的結果將做爲外部的輸入信息!例如 uname -r 會顯示出目前的核心版本,而我們的核心版本在 /lib/modules 裏面,因此,你可以先運行 uname -r 找出核心版本,然後再以『 cd 目錄』到該目錄下,當然也可以運行如同上面範例六的運行內容囉。 

另外再舉個例子,我們也知道, locate 命令可以列出所有的相關文件檔名,但是,如果我想要知道各個文件的權限呢?舉例來說,我想要知道每個 crontab 相關檔名的權限:
[root@www ~]# ls -l `locate crontab`
如此一來,先以 locate 將文件名數據都列出來,再以 ls 命令來處理的意思啦!瞭了嗎? ^_^

例題:
若你有一個常去的工作目錄名稱爲:『/cluster/server/work/taiwan_2005/003/』,如何進行該目錄的簡化?
答:
在一般的情況下,如果你想要進入上述的目錄得要『cd /cluster/server/work/taiwan_2005/003/』, 以鳥哥自己的案例來說,鳥哥跑數值模式常常會配置很長的目錄名稱(避免忘記),但如此一來變換目錄就很麻煩。 此時,鳥哥習慣利用底下的方式來降低命令下達錯誤的問題:
[root@www ~]# work="/cluster/server/work/taiwan_2005/003/"
[root@www ~]# cd $work
未來我想要使用其他目錄作爲我的模式工作目錄時,只要變更 work 這個變量即可!而這個變量又可以在bash 的配置文件中直接指定,那我每次登陸只要運行『 cd $work 』就能夠去到數值模式仿真的工作目錄了!是否很方便呢? ^_^

Tips:
老實說,使用『 version=$(uname -r) 』來取代『 version=`uname -r` 』比較好,因爲反單引號大家老是容易打錯或看錯! 所以現在鳥哥都習慣使用 $( 命令 ) 來介紹這個功能!

 變量內容的刪除、取代與測試、替換


 變量內容的刪除與取代

1、刪除:

  1. # :符合取代文字的『最短的』那一個; 
  2. ##:符合取代文字的『最長的』那一個 ;

eg:『從前面開始刪除變量內容』

eg:『從後面向前刪除變量內容』

 

由於我是想要由變量內容的後面向前面刪除,而我這個變量內容最後面的結尾是『/root/bin』, 所以你可以看到上面我刪除的數據最終一定是『bin』,亦即是『:*bin』那個 * 代表通配符! 至於 % 與 %% 的意義其實與 # 及 ## 類似!這樣理解否?

例題:
假設你是 root ,那你的 MAIL 變量應該是 /var/spool/mail/root 。假設你只想要保留最後面那個檔名 (root), 前面的目錄名稱都不要了,如何利用 $MAIL 變量來達成?
答:

題意其實是這樣『/var/spool/mail/root』,亦即刪除掉兩條斜線間的所有數據(最長符合)。 這個時候你就可以這樣做即可:

  1. [root@www ~]# echo ${MAIL##/*/} 

相反的,如果你只想要拿掉文件名,保留目錄的名稱,亦即是『/var/spool/mail/root』 (最短符合)。但假設你並不知道結尾的字母爲何,此時你可以利用通配符來處理即可,如下所示:

  1. [root@www ~]# echo ${MAIL%/*} 

 

2、取代:

 變量的測試與內容替換

 在某些時刻我們常常需要『判斷』某個變量是否存在,若變量存在則使用既有的配置,若變量不存在則給予一個常用的配置。

不過這還是有點問題!因爲 username 可能已經被配置爲『空字符串』了!果真如此的話,那你還可以使用底下的範例來給予 username 的內容成爲 root 喔!

在大括號內有沒有冒號『 : 』的差別是很大的!加上冒號後,被測試的變量未被配置或者是已被配置爲空字符串時, 都能夠用後面的內容 (本例中是使用 root 爲內容) 來替換與配置!

如果你想要將舊變量內容也一起替換掉的話,那麼就使用等號 (=) 吧!

那如果我只是想知道,如果舊變量不存在時,整個測試就告知我『有錯誤』,此時就能夠使用問號『 ? 』的幫忙啦!

 文章出自:http://vbird.dic.ksu.edu.tw/linux_basic/0320bash_2.php#variable_other_re《鳥哥的linux私房菜》,請尊重原作者的勞動成果!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章