概要:
shell中,變量有環境變量和自定義變量之分,環境 變量相當於全局變量,自定義變量相當於局部變量,因此父程序的環境變量變量會被子程序所引用,而自定義變量則不可以。其中的原因在於子程序僅會繼承父程序的環境變量, 子程序不會繼承父程序的自定義變量。
- 爲什麼環境變量的數據可以被子程序所引用呢?這是因爲內存配置的關係!理論上是這樣的:
- 當啓動一個 shell,操作系統會分配一記憶區塊給 shell 使用,此內存內之變量可讓子程序取用
- 若在父程序利用 export 功能,可以讓自定義變量的內容寫到上述的記憶區塊當中(環境變量);
- 當加載另一個 shell 時 (亦即啓動子程序,而離開原本的父程序了),子 shell 可以將父 shell 的環境變量所在的記憶區塊導入自己的環境變量區塊當中。
echo --顯示變量內容 |
- 格式:echo $variable
- echo ${variable}
- echo $PATH
- /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
- [root@www ~]# echo ${PATH}
- /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
unset --取消變量 |
- 格式:unset 變量名稱
- 取消 myname 的配置:
- [root@www ~]#unset myname
env --觀察環境變量 |
- 範例一:列出目前的 shell 環境下的所有環境變量與其內容。
- [root@www ~]# env
- HOSTNAME=www.vbird.tsai <== 這部主機的主機名
- TERM=xterm <== 這個終端機使用的環境是什麼類型
- SHELL=/bin/bash <== 目前這個環境下,使用的 Shell 是哪一個程序?
- HISTSIZE=1000 <== 『記錄命令的筆數』在 CentOS 默認可記錄 1000 筆
- USER=root <== 使用者的名稱啊!
- 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:
- or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0
- 0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=
- 00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3
- 1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00
- ;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些顏色顯示
- MAIL=/var/spool/mail/root <== 這個用戶所取用的 mailbox 位置
- PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:
- /root/bin <== 不再多講啊!是運行文件命令搜尋路徑
- INPUTRC=/etc/inputrc <== 與鍵盤按鍵功能有關。可以配置特殊按鍵!
- PWD=/root <== 目前用戶所在的工作目錄 (利用 pwd 取出!)
- LANG=en_US <== 這個與語系有關,底下會再介紹!
- HOME=/root <== 這個用戶的家目錄啊!
- _=/bin/env <== 上一次使用的命令的最後一個參數(或命令本身)
部分環境變量的介紹如下:
- HOME
- 代表用戶的家目錄。還記得我們可以使用 cd ~ 去到自己的家目錄嗎?或者利用 cd 就可以直接回到用戶家目錄了。那就是取用這個變量啦~ 有很多程序都可能會取用到這個變量的值!
- SHELL
- 告知我們,目前這個環境使用的 SHELL 是哪支程序? Linux 默認使用 /bin/bash 的啦!
- HISTSIZE
- 這個與『歷史命令』有關,亦即是, 我們曾經下達過的命令可以被系統記錄下來,而記錄的『筆數』則是由這個值來配置的。
- 當我們使用 mail 這個命令在收信時,系統會去讀取的郵件信箱文件 (mailbox)。
- PATH
- 就是運行文件搜尋的路徑啦~目錄與目錄中間以冒號(:)分隔, 由於文件的搜尋是依序由 PATH 的變量內的目錄來查詢,所以,目錄的順序也是重要的喔。
- LANG
- 這個重要!就是語系數據囉~很多信息都會用到他, 舉例來說,當我們在啓動某些 perl 的程序語言文件時,他會主動的去分析語系數據文件, 如果發現有他無法解析的編碼語系,可能會產生錯誤喔!一般來說,我們中文編碼通常是 zh_TW.Big5 或者是 zh_TW.UTF-8,這兩個編碼偏偏不容易被解譯出來,所以,有的時候,可能需要修訂一下語系數據。 這部分我們會在下個小節做介紹的!
- RANDOM
- 這個玩意兒就是『隨機隨機數』的變量啦!目前大多數的 distributions 都會有隨機數生成器,那就是 /dev/random 這個文件。 我們可以透過這個隨機數文件相關的變量 ($RANDOM) 來隨機取得隨機數值喔。在 BASH 的環境下,這個 RANDOM 變量的內容,介於 0~32767 之間,所以,你只要 echo $RANDOM 時,系統就會主動的隨機取出一個介於 0~32767 的數值。萬一我想要使用 0~9 之間的數值呢?呵呵~利用 declare 宣告數值類型, 然後這樣做就可以了:
- [root@www ~]# declare -i number=$RANDOM*10/32768
- [root@www ~]# echo $number
- 8 <== 此時會隨機取出 0~9 之間的數值喔!
set --觀察環境變量與自定義變量 |
- 一般來說,不論是否爲環境變量,只要跟我們目前這個 shell 的操作接口有關的變量, 通常都會被配置爲大寫字符,也就是說,『基本上,在 Linux 默認的情況中,使用{大寫的字母}來配置的變量一般爲系統內定需要的變量』。 OK!OK!那麼上頭那些變量當中,有哪些是比較重要的?大概有這幾個吧!
- PS1:(提示字符的配置)
- 這是 PS1 (數字的 1 不是英文字母),這個東西就是我們的『命令提示字符』喔! 當我們每次按下 [Enter] 按鍵去運行某個命令後,最後要再次出現提示字符時, 就會主動去讀取這個變量值了。上頭 PS1 內顯示的是一些特殊符號,這些特殊符號可以顯示不同的信息, 每個 distributions 的 bash 默認的 PS1 變量內容可能有些許的差異,不要緊,『習慣你自己的習慣』就好了。 你可以用 man bash (注3)去查詢一下 PS1 的相關說明,以理解底下的一些符號意義。
- \d :可顯示出『星期 月 日』的日期格式,如:"Mon Feb 2"
- \H :完整的主機名。舉例來說,鳥哥的練習機爲『www.vbird.tsai』
- \h :僅取主機名在第一個小數點之前的名字,如鳥哥主機則爲『www』後面省略
- \t :顯示時間,爲 24 小時格式的『HH:MM:SS』
- \T :顯示時間,爲 12 小時格式的『HH:MM:SS』
- \A :顯示時間,爲 24 小時格式的『HH:MM』
- \@ :顯示時間,爲 12 小時格式的『am/pm』樣式
- \u :目前使用者的賬號名稱,如『root』;
- \v :BASH 的版本信息,如鳥哥的測試主板本爲 3.2.25(1),僅取『3.2』顯示
- \w :完整的工作目錄名稱,由根目錄寫起的目錄名稱。但家目錄會以 ~ 取代;
- \W :利用 basename 函數取得工作目錄名稱,所以僅會列出最後一個目錄名。
- \# :下達的第幾個命令。
- \$ :提示字符,如果是 root 時,提示字符爲 # ,否則就是 $ 囉~
- 好了,讓我們來看看 CentOS 默認的 PS1 內容吧:『[\u@\h \W]\$ 』,現在你知道那些反斜槓後的數據意義了吧? 要注意喔!那個反斜槓後的數據爲 PS1 的特殊功能,與 bash 的變量配置沒關係啦!不要搞混了喔! 那你現在知道爲何你的命令提示字符是:『 [root@www ~]# 』了吧? 好了,那麼假設我想要有類似底下的提示字符:
- [root@www /home/dmtsai 16:50 #12]#
- 那個 # 代表第 12 次下達的命令。那麼應該如何配置 PS1 呢?可以這樣啊:
- [root@www ~ ]# cd /home
- [root@www home]# PS1='[\u@\h \w \A #\#]\$ '
- [root@www /home 17:02 #85]#
- # 看到了嗎?提示字符變了!變的很有趣吧!其中,那個 #85 比較有趣,
- # 如果您再隨便輸入幾次 ls 後,該數字就會添加喔!爲啥?上面有說明滴!
- $:(關於本 shell 的 PID)
- 錢字號本身也是個變量喔!這個咚咚代表的是『目前這個 Shell 的線程代號』,亦即是所謂的 PID (Process ID)。 更多的程序觀念,我們會在第四篇的時候提及。想要知道我們的 shell 的 PID ,就可以用:『 echo $$ 』即可!出現的數字就是你的 PID 號碼。
- ?:(關於上個運行命令的回傳值)
- 什麼?問號也是一個特殊的變量?沒錯!在 bash 裏面這個變量可重要的很! 這個變量是:『上一個運行的命令所回傳的值』, 上面這句話的重點是『上一個命令』與『回傳值』兩個地方。當我們運行某些命令時, 這些命令都會回傳一個運行後的代碼。一般來說,如果成功的運行該命令, 則會回傳一個 0 值,如果運行過程發生錯誤,就會回傳『錯誤代碼』纔對!一般就是以非爲 0 的數值來取代。 我們以底下的例子來看看:
- [root@www ~]# echo $SHELL
- /bin/bash <==可順利顯示!沒有錯誤!
- [root@www ~]# echo $?
- 0 <==因爲沒問題,所以回傳值爲 0
- [root@www ~]# 12name=VBird
- -bash: 12name=VBird: command not found <==發生錯誤了!bash回報有問題
- [root@www ~]# echo $?
- 127 <==因爲有問題,回傳錯誤代碼(非爲0)
- # 錯誤代碼回傳值依據軟件而有不同,我們可以利用這個代碼來搜尋錯誤的原因喔!
- [root@www ~]# echo $?
- 0
- # 咦!怎麼又變成正確了?這是因爲 "?" 只與『上一個運行命令』有關,
- # 所以,我們上一個命令是運行『 echo $? 』,當然沒有錯誤,所以是 0 沒錯!
- OSTYPE, HOSTTYPE, MACHTYPE:(主機硬件與核心的等級)
- 我們在第零章、計算器概論內的 CPU 等級說明中談過 CPU , 目前個人計算機的 CPU 主要分爲 32/64 位,其中 32 位又可分爲 i386, i586, i686,而 64 位則稱爲 x86_64。 由於不同等級的 CPU 命令集不太相同,因此你的軟件可能會針對某些 CPU 進行優化,以求取較佳的軟件性能。 所以軟件就有 i386, i686 及 x86_64 之分。以目前 (2009) 的主流硬件來說,幾乎都是 x86_64 的天下! 但是畢竟舊機器還是非常多,以鳥哥的環境來說,我用 P-III 等級的計算機,所以上頭就發現我的等級是 i686 啦!
- 要留意的是,較高階的硬件通常會向下兼容舊有的軟件,但較高階的軟件可能無法在舊機器上面安裝! 我們在第三章就曾說明過, 這裏再強調一次,你可以在 x86_64 的硬件上安裝 i386 的 Linux 操作系統,但是你無法在 i686 的硬件上安裝 x86_64 的 Linux 操作系統!這點得要牢記在心!
export --自定義變量轉成環境變量 |
export可以將自定義變量變成環境變量,讓該變量值繼續存在於子程序,讓該變量內容繼續的在子程序中使用。
- 格式:export 變量名稱
如果僅下達 export 而沒有接變量時,那麼此時將會把所有的『環境變量』顯示出來!例如:
- [root@www ~]# export
- declare -x HISTSIZE="1000"
- declare -x HOME="/root"
- declare -x HOSTNAME="www.vbird.tsai"
- declare -x INPUTRC="/etc/inputrc"
- declare -x LANG="en_US"
- declare -x LOGNAME="root"
declare / typeset --宣告變量的類型(也可以將環境變量轉成自定義變量) |
declare 語法如下:
如果你不小心將變量配置爲『只讀』,通常得要註銷再登陸才能復原該變量的類型了!
在默認的情況底下, bash 對於變量有幾個基本的定義:
- 變量類型默認爲『字符串』,所以若不指定變量類型,則 1+2 爲一個『字符串』而不是『計算式』。 所以上述第一個運行的結果纔會出現那個情況的;
- bash 環境中的數值運算,默認最多僅能到達整數形態,所以 1/3 結果是 0;
- 1.變量名稱只能是英文字母與數字,但是開頭字符不能是數字,如下爲錯誤:
- 『2myname=VBird』
- 2.等號兩邊不能直接接空格符,如下所示爲錯誤:
- 『myname = VBird』或『myname=VBird Tsai』
- 3.變量內容若有空格符可使用雙引號『"』或單引號『'』將變量內容結合起來,但
- 雙引號內的特殊字符如 $ 等,可以保有原本的特性,如下所示:
- 『var="lang is $LANG"』則『echo $var』可得『lang is en_US』
- 單引號內的特殊字符則僅爲一般字符 (純文本),如下所示:
- 『var='lang is $LANG'』則『echo $var』可得『lang is $LANG』
- 4.在一串命令中,還需要藉由其他的命令提供的信息,可以使用反單引號『`命令`』或 『$(命令)』。特別注意,那個 ` 是鍵盤上方的數字鍵 1 左邊那個按鍵,而不是單引號! 例如想要取得核心版本的配置:
- 『version=$(uname -r)』再『echo $version』可得『2.6.18-128.el5』
- 5.可用跳脫字符『 \ 』將特殊符號(如 [Enter], $, \, 空格符, '等)變成一般字符;
- 6.若該變量爲擴增變量內容時,則可用 "$變量名稱" 或 ${變量} 累加內容,如下所示:
- 『PATH="$PATH":/home/bin』
- 7.通常大寫字符爲系統默認變量,自行配置變量可以使用小寫字符,方便判斷 (純粹依照使用者興趣與嗜好) ;
- 8.若該變量需要在其他子程序運行,則需要以 export 來使變量變成環境變量:
- 『export PATH』
舉例如下:
根據上面的案例你可以試試看!就可以瞭解變量的配置囉!這個是很重要的呦!請勤加練習! 其中,較爲重要的一些特殊符號的使用囉!例如單引號、雙引號、跳脫字符、錢字號、反單引號等等,底下的例題想一想吧!例題:
例題:
在變量的配置當中,單引號與雙引號的用途有何不同?
答:
單引號與雙引號的最大不同在於雙引號仍然可以保有變量的內容,但單引號內僅能是一般字符 ,而不會有特殊符號。我們以底下的例子做說明:假設您定義了一個變量, name=VBird ,現在想以 name 這個變量的內容定義出 myname 顯示 VBird its me 這個內容,要如何訂定呢?
[root@www ~]# name=VBird發現了嗎?沒錯!使用了單引號的時候,那麼 $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/"未來我想要使用其他目錄作爲我的模式工作目錄時,只要變更 work 這個變量即可!而這個變量又可以在bash 的配置文件中直接指定,那我每次登陸只要運行『 cd $work 』就能夠去到數值模式仿真的工作目錄了!是否很方便呢? ^_^ |
Tips: |
變量內容的刪除與取代 |
- # :符合取代文字的『最短的』那一個;
- ##:符合取代文字的『最長的』那一個 ;
eg:『從前面開始刪除變量內容』
eg:『從後面向前刪除變量內容』
由於我是想要由變量內容的後面向前面刪除,而我這個變量內容最後面的結尾是『/root/bin』, 所以你可以看到上面我刪除的數據最終一定是『bin』,亦即是『:*bin』那個 * 代表通配符! 至於 % 與 %% 的意義其實與 # 及 ## 類似!這樣理解否?
例題:
假設你是 root ,那你的 MAIL 變量應該是 /var/spool/mail/root 。假設你只想要保留最後面那個檔名 (root), 前面的目錄名稱都不要了,如何利用 $MAIL 變量來達成?
答:
題意其實是這樣『/var/spool/mail/root』,亦即刪除掉兩條斜線間的所有數據(最長符合)。 這個時候你就可以這樣做即可:
相反的,如果你只想要拿掉文件名,保留目錄的名稱,亦即是『/var/spool/mail/root』 (最短符合)。但假設你並不知道結尾的字母爲何,此時你可以利用通配符來處理即可,如下所示:
|
變量的測試與內容替換 |
在某些時刻我們常常需要『判斷』某個變量是否存在,若變量存在則使用既有的配置,若變量不存在則給予一個常用的配置。
不過這還是有點問題!因爲 username 可能已經被配置爲『空字符串』了!果真如此的話,那你還可以使用底下的範例來給予 username 的內容成爲 root 喔!
在大括號內有沒有冒號『 : 』的差別是很大的!加上冒號後,被測試的變量未被配置或者是已被配置爲空字符串時, 都能夠用後面的內容 (本例中是使用 root 爲內容) 來替換與配置!
如果你想要將舊變量內容也一起替換掉的話,那麼就使用等號 (=) 吧!
那如果我只是想知道,如果舊變量不存在時,整個測試就告知我『有錯誤』,此時就能夠使用問號『 ? 』的幫忙啦!
文章出自:http://vbird.dic.ksu.edu.tw/linux_basic/0320bash_2.php#variable_other_re,《鳥哥的linux私房菜》,請尊重原作者的勞動成果!