轉載:http://www.blogjava.net/jasmine214--love/archive/2010/11/26/339106.htmlhtml
本文將會講解一些linux中命令的使用與技巧但願對新手給予幫助
一 eval命令將會首先掃描命令行進行全部的置換,而後再執行該命令。該命令適用於那些一次掃描沒法實現其功能的變量。該命令對變量進行兩次掃描。這些須要進行兩次掃描的變量有時被稱爲複雜變量。不過這些變量自己並不複雜。
1 eval命令也能夠用於回顯簡單變量,不必定是複雜變量java
[neau@mail ~]$ NAME=VALUEBANK [neau@mail ~]$ VALUEBANK [neau@mail ~]$ echo $NAME VALUEBANK
2 執行含有字符串的命令
首先咱們首先建立一個名爲test的小文件,在這個小文件中含有一些文本。接着,將cat test賦給變量myfile,如今咱們e c h o該變量,看看是否可以執行上述命令。
linux
[neau@mail ~]$ vi test [neau@mail ~]$ cat test Hello World!!! I am a chinese Boy!
將cat testf賦給變量myfile
[neau@mail ~]$ myfile="cat test"
若是咱們e c h o該變量,咱們將沒法列出t e s t 文件中的內容。
程序員
[neau@mail ~]$ echo $myfile cat test
讓咱們來試一下e v a l命令,記住e v a l命令將會對該變量進行兩次掃瞄。
shell
[neau@mail ~]$ Hello World!!! I am a chinese Boy!
從上面的結果能夠看出,使用e v a l命令不但能夠置換該變量,還可以執行相應的命令。第
一次掃描進行了變量置換,第二次掃描執行了該字符串中所包含的命令cat test。
3 命令還能夠用來顯示出傳遞給腳本的最後一個參數
數據庫
[neau@mail ~]$ cat test1 #!/bin/bash echo "Total of the arguments passed $#"
echo "The process Id is $$"
echo "Last argument os "$( [neau@mail ~]$ ./test1 value bank test last Total of the arguments passed 4 The process Id is 21545 Last argument os last
在上面的腳本中, e v a l命令首先把$ $ #解析爲當前s h e l l的參數個數,而後在第二次掃描時
得出最後一個參數。
4 給每一個值一個變量名
能夠給一個值一個變量名。下面我對此作些解釋,假定有一個名爲test2的文件:
編程
[neau@mail ~]$ cat test2 CCTV 5 CHANGEL SPORTS LIKE YES
你但願該文件中的第一列成爲變量名,第二列成爲該變量的值,這樣就能夠:
bash
[neau@mail ~]$ cat test2 COMMANY TQ LANGUE ENGLISH LIKE YES [neau@mail ~]$ cat test3 #!/bin/bash while read NAME VALUE do
done <test2 echo "$COMMANY $LANGUE $LIKE" [neau@mail ~]$ ./test3 TQ ENGLISH YES
轉載自 http://www.blogjava.net/jasmine214--love/archive/2010/11/26/339106.html函數
1. eval command-line 學習
其中command-line是在終端上鍵入的一條普通 命令行。然而當在它前面放上eval時,其結果是shell在執行命令行以前掃描它兩次。如:
pipe="|"
eval ls $pipe wc -l
shell第1次掃描命令行時,它替換出pipe的 值|,接着eval使它再次掃描命令行,這時shell把| 做爲管道符號了。
若是變量中包含任何須要shell直接在命令行中看到的字符(不是替換的結果),就可使用eval。命令行結束符(;| &),I/o重 定向符(< >)和引號就屬於對shell具備特殊意義的符號,必須直接出如今命令行中。
2. eval echo \$$# 取得最後一個參數
如:cat last
eval echo \$$#
./last one two three four
four
第一遍掃描 後,shell把反斜槓去掉了。當shell再 次掃描該行時,它替換了$4的值,並執行echo命 令
3.如下示意如何用eval命令建立指向變量的「指 針」:
x=100
ptrx=x
eval echo \$$ptrx 指向ptrx,用這裏的方法能夠理解b中的例 子
100 打印100
eval $ptrx=50 將50存到ptrx指向的變量中。
echo $x
50 打印50
功能是:建立一個mkdircd函數(加在.bashrc文件中,能夠建立一個mkdircd命令),用於建立新一個目錄並同時cd到些目錄中(不少狀況下,咱們建立一個新的目錄後,老是要進入這個目錄中,使用此命令能夠在一個命令中完成此功能)。
看到代碼時,不明白命令中eval的做用,後來查了一個資料,發現eval的功能以下:
語法:eval cmdLine
eval會對後面的cmdLine進行兩遍掃描,若是第一遍掃描後,cmdLine是個普通命令,則執行此命令;若是cmdLine中含有變量的間接引用,則保證間接引用的語義。
舉例以下:
set 11 22 33 44
若是要輸出最近一個參數,即44,可使用以下命令,
echo $4
可是若是咱們不知道有幾個參數的時候,要輸出最後一個參數,你們可能會想到使用$#來輸出最後一個參數,
若是使用命令:
echo "\$$#"
則獲得的結果是 $4,而不是咱們想要的44。這裏涉及到一個變量間接引用的問題,咱們的本意是輸出 $4,默認狀況下,命令後忽略變量間接引用的狀況。
這時候,就可使用eval命令。
eval echo "\$$#"
獲得的結果爲44
轉載自:http://www.linuxso.com/shell/13692.html
1、bash命令處理的12個步驟;
一、將命令行分紅由固定元字符集分隔的記號;
SPACE, TAB, NEWLINE, ; , (, ), <, >, |, &
記號類型包括單詞,關鍵字,I/O重定向符和分號。
二、檢測每一個命令的第一個記號,查看是否爲不帶引號或反斜線的關鍵字。
若是是一個開放的關鍵字,如if和其餘控制結構起始字符串,function,{或(,則命令實際上爲一複合命令。shell在內部對複合命令進行處理,讀取下一個命令,並重復這一過程。若是關鍵字不是複合命令起始字符串(如then等一個控制結構中間出現的關鍵字),則給出語法錯誤信號。
三、依據alias.html' target='_blank'>別名列表檢查每一個命令的第一個關鍵字;
若是找到相應匹配,則替換其別名定義,並退回第一步;不然進入第4步。該策略容許遞歸別名,還容許定義關鍵字別名。如alias procedure=function
四、執行大括號擴展,例如a{b,c}變成ab ac
五、若是~位於單詞開頭,用$HOME替換~。
使用usr的主目錄替換~user。
六、對任何以符號$開頭的表達式執行參數(變量)替換;
七、對形式$(string)的表達式進行命令替換;
這裏是嵌套的命令行處理。
八、計算形式爲$((string))的算術表達式;
九、把行的參數,命令和算術替換部分再次分紅單詞,此次它使用$IFS中的字符作分割符而不是步驟1的元字符集;
十、對出現*, ?, [ / ]對執行路徑名擴展,也稱爲通配符擴展;
十一、按命令優先級表(跳過別名),進行命令查尋;
十二、設置完I/O重定向和其餘操做後執行該命令。
2、關於引用
一、單引號跳過了前10個步驟,不能在單引號裏放單引號
二、雙引號跳過了步驟1~5,步驟9~10,也就是說,只處理6~8個步驟。
也就是說,雙引號忽略了管道字符,別名,~替換,通配符擴展,和經過分隔符分裂成單詞。
雙引號裏的單引號沒有做用,但雙引號容許參數替換,命令替換和算術表達式求值。能夠在雙引號裏包含雙引號,方式是加上轉義符"\",還必須轉義$, `, \。
3、eval的做用;
eval的做用是再次執行命令行處理,也就是說,對一個命令行,執行兩次命令行處理。這個命令要用好,就要費必定的功夫。我舉兩個例子,拋磚引玉。
一、例子1:用eval技巧實現shell的控制結構for
用eval技巧實現shell的控制結構for。
[root@home root]# cat myscript1
#!/bin/sh
evalit(){
if [ $cnt = 1 ];then
eval $@
return
else
let cnt=cnt-1
evalit $@
fi
eval $@
}
cnt=$1
echo $cnt | egrep "^[1-9][0-9]*$" >/dev/null
if [ $? -eq 0 ]; then
shift
evalit $@
else
echo 'ERROR!!! Check your input!'
fi
[root@home root]# ./myscript1 3 hostname home home home [root@home root]# ./myscript1 5 id |cut -f1 -d' ' uid=0(root) uid=0(root) uid=0(root) uid=0(root) uid=0(root)
注意:bash裏有兩個很特殊的變量,它們保存了參數列表。
$* ,保存了以$IFS指定的分割符所分割的字符串組。
$@ ,原樣保存了參數列表,也就是 "$1""$2"...
這裏我使用了函數遞歸以及eval實現了for結構。
當執行eval $@時,它經歷了步驟以下:
第1步,分割成eval $@
第6步,擴展$@爲hostname
第11步,找到內置命令eval
重複一次命令行處理,第11步,找到hostname命令,執行。
注意:也許有人想固然地認爲,何須用eval呢?直接$@來執行命令就能夠了嘛。
例子2:一個典型錯誤的例子
錯誤!這裏給個典型的例子你們看看。
[root@home root]# a="id | cut -f1 -d' '" [root@home root]# $a
id:無效選項 -- f
請嘗試執行‘id --help’來獲取更多信息。
[root@home root]# eval $a uid=0(root)
若是命令行復雜的話(包括管道或者其餘字符),直接執行$a字符串的內容就會出錯。分析以下。
$a的處理位於第6步──參數擴展,也就是說,跳過了管道分析,因而"|", "cut", "-f1", "-d"都變成了id命令的參數,固然就出錯啦。
但使用了eval,它把第一遍命令行處理所得的"id", "|", "cut", "-f1", "-d"這些字符串再次進行命令行處理,此次就能正確分析其中的管道了。
總而言之:要保證你的命令或腳本設計能正確經過命令行處理,跳過任意一步,均可能形成意料外的錯誤!
例子3:設置系統的ls色彩顯示
eval $(dircolors -b /etc/dircolors)
eval語句通知shell接受eval參數,並再次經過命令行處理的全部步驟運行它們。
它使你能夠編寫腳本隨意建立命令字符串,而後把它們傳遞給shell執行;
$() 是命令替換,返回命令的輸出字符串。
其中dircolors命令根據/etc/dircolors配置文件生成設置環境變量LS_COLORS的bash代碼,內容以下
[root@localhost root]# dircolors -b > tmp [root@localhost root]# cat tmp LS_COLORS='no=00:fi=00:di=01;34:ln=01; ......
export LS_COLORS
#這裏我沒有指定配置文件,因此dircolors按預置數據庫生成代碼。
其輸出被eval命令傳遞給shell執行。
eval是對Bash Shell命令行處理規則的靈活應用,進而構造"智能"命令實現複雜的功能。
上面說起的命令是eval其中一個很普通的應用,它重複了1次命令行參數傳遞過程,純粹地執行命令的命令。
其實它是bash的難點,是高級bash程序員的必修之技。
4、命令優先級表
一、別名
二、關鍵字
三、函數
四、內置命令
五、腳本或可執行程序($PATH)
5、鑑於一些學習中會遇到的困惑,我再給出一些有趣的命令。
一、command builtin enable
上面的命令行說起過,第11步會進行命令查找,那它的具體過程如何呢?
它的默認查找次序爲函數,內部命令,腳本和可執行代碼。咱們每每要在實際編程中跳過一些查找項以知足必定的功能需求。這時候就要用到這三個命令來施展魔法~~
二、command
跳過別名和函數的查找,換句話說,它只查找內部命令以及搜索路徑中找到的腳本或可執行程序。
這裏舉個有趣的例子。
[root@home root]# type -all pwd
pwd is a shell builtin pwd is /bin/pwd [root@home root]# cat myscript2
#!/bin/sh
pwd(){
echo "This is the current directory."
command pwd
}
pwd
[root@home root]# ./myscript2 This is the current directory. /root
我用pwd()函數取代了內置命令pwd以及外部命令/bin/pwd,而後在腳本里執行內置命令pwd。在這裏咱們爲何要用command呢?是爲了不函數陷入遞歸循環,由於函數名與內置命令同名,而函數的優先級比內置命令高。
三、builtin
顧名思義,它只查找內置命令。這個命令很簡單,就很少說了。
四、enable
與builtin相反,它屏蔽一個內置命令,容許運行一個shell腳本或同名的可執行代碼而無須給出徹底路徑名。
舉個例子吧。
pwd命令有兩個,一個是shell內置的,一個是可執行程序。
當執行一些奇怪的路徑名後,shell內置的pwd會打印出"錯誤信息",但外部的pwd會打印出當前目錄的"原來面目"。請看下面:
[root@home root]# cd // [root@home //]# pwd // [root@home //]# type -all pwd
pwd is a shell builtin pwd is /bin/pwd [root@home //]# /bin/pwd
/ [root@home //]# enable -n pwd
[root@home //]# pwd
/
這樣,用enable -n屏蔽內置pwd命令後,就能夠用外部pwd打印出正確的路徑名了。
Bash博大精深,但願你們好好學習。:)
看到另一個例子,也很實用
給每一個值一個變量名
能夠給一個值一個變量名。下面我對此作些解釋,假定有一個名爲test2的文件:
[neau@mail ~]$ cat test2 CCTV 5 CHANGEL SPORTS LIKE YES
你但願該文件中的第一列成爲變量名,第二列成爲該變量的值,這樣就能夠:
[neau@mail ~]$ cat test2 COMMANY TQ LANGUE ENGLISH LIKE YES [neau@mail ~]$ cat test3
#!/bin/bash
while read NAME VALUE
do
eval "${NAME}=${VALUE}"
done <test2
echo "$COMMANY $LANGUE $LIKE"
[neau@mail ~]$ ./test3 TQ ENGLISH YES