Linux之eval命令使用方法詳解

eval命令將會首先掃描命令行進行所有的替換,類似于C語言中的宏替換,然后再執(zhí)行命令。該命令使用于那些一次掃描無法實現(xiàn)其功能的變量。該命令對變量進行兩次掃描。這些需要進行兩次掃描的變量有時候被稱為復雜變量。

新建一個文件test將字符串”helloworld!“寫入文件中,把cat test賦值給變量word,如果我們echo word并不能的到test中的內(nèi)容;然而eval word則能顯示文件中的內(nèi)容,因為eval命令對后面的命令進行了兩次掃描,第一次將word替換為 cat test,第二次執(zhí)行cat test。

Linux之eval命令使用方法詳解

2.eval也可以用于回寫簡單變量,不一定是復雜變量。
?? ?NAME=ZONE
?? ?eval echo $NAME等價于echo $NAME
Linux之eval命令使用方法詳解
3、eval命令還可以獲取傳給shell的最后一個參數(shù)?
如果我們知道參數(shù)個數(shù),我們想要查看最后一個參數(shù)的內(nèi)容可以使用echo直接顯示,如輸入 first last兩個參數(shù)我們可以用echo?$2 來查看最后一個參數(shù);?

但是,如果我們不知道參數(shù)個數(shù)還想查看最后一個參數(shù)內(nèi)容該怎么辦呢?這是我們就想到使用?$$#為傳給shell腳本的參數(shù)個數(shù),但是上例中 echo “$$#”后顯示的其實是參數(shù)個數(shù),而使用eval echo “$$#”才顯示最后一個參數(shù)的內(nèi)容。?

Linux之eval命令使用方法詳解

Linux之eval命令使用方法詳解

對上述第3點補充:???  ????今天學習eval命令時,發(fā)現(xiàn)了這個問題:???  ????echo?"Last?argument?is?$(eval?echo?$$#)"?a?b?c?d?e???  ????這句話本意打印:Last?argument?is?e???  ????但實際打印的是:Last?argument?is?-bash?a?b?c?d?e???  ???  ????$#一般用在腳本中的,用在命令行的話就要先使用set設置位置參數(shù),因此修改為如下:???  ????set?-?a?b?c?d?e???  ????echo?"Last?argument?is?$(eval?echo?$$#)"???  ????Last?argument?is?e???  ???  ????set?-?a?b?c?d?e?f???  ????echo?"Last?argument?is?$(eval?echo?$#)"???  ????Last?argument?is?6

4、條件篩選?

在file文件中寫入兩列數(shù)據(jù),第一列對應KEY 、第二列為VALUE,使用eval命令將KEY與VALUE的值對應起來,從文件中讀取?

eval進階:

?? ?1.shell 也提供了 eval 命令,如同熟悉的其他腳本語言,會將它的參數(shù)做為命令執(zhí)行,初看會疑惑為什么shell要提供兩種動態(tài)執(zhí)行命令字串的機制,但是經(jīng)過仔細分析,才發(fā)現(xiàn)shell的eval同其他語言有很大區(qū)別。
?? ?2.shell 中的 eval
?? ??? ?2.1 不能獲得函數(shù)處理結(jié)果 ,如1所說,所有命令,函數(shù)的處理結(jié)果只能通過 “來獲得,那么其它語言中利用eval來獲得動態(tài)生成代碼執(zhí)行后的輸出變得不可能。
?? ??? ?2.2 eval 嵌套無意義 ,在其他語言中可以通過 eval(eval(“code”)),來執(zhí)行(執(zhí)行動態(tài)生成的code的返回),而由于shell 中 eval 將后面的eval命令簡單當作命令字符串執(zhí)行,失去了嵌套作用,嵌套被命令替換取代。

eval的作用是再次執(zhí)行命令行處理,也就是說,對一個命令行,執(zhí)行兩次命令行處理。這個命令要用好,就要費一定的功夫。我舉兩個例子,拋磚引玉.

例子1:用eval技巧實現(xiàn)shell的控制結(jié)構(gòu)for

[root@home?root]#?cat?myscript1????  QUOTE:????  #!/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里有兩個很特殊的變量,它們保存了參數(shù)列表。????  ????  $*,保存了以$IFS指定的分割符所分割的字符串組。????  $@,原樣保存了參數(shù)列表,也就是"$1""$2"...

這里我使用了函數(shù)遞歸以及eval實現(xiàn)了for結(jié)構(gòu)。
當執(zhí)行eval $@時,它經(jīng)歷了步驟如下:
第1步,分割成eval $@
第6步,擴展$@為hostname
第11步,找到內(nèi)置命令eval
重復一次命令行處理,第11步,找到hostname命令,執(zhí)行。

注意:也許有人想當然地認為,何必用eval呢?直接$@來執(zhí)行命令就可以了嘛。

例子2:一個典型錯誤的例子

Linux之eval命令使用方法詳解

如果命令行復雜的話(包括管道或者其他字符),直接執(zhí)行$a字符串的內(nèi)容就會出錯。分析如下。
$a的處理位于參數(shù)擴展,也就是說,跳過了管道分析,于是”|”, “cut”, “-f1”, “-d”都變成了id命令的參數(shù),當然就出錯啦。
但使用了eval,它把第一遍命令行處理所得的”id”, “|”, “cut”, “-f1”, “-d”這些字符串再次進行命令行處理,這次就能正確分析其中的管道了。
總而言之:要保證你的命令或腳本設計能正確通過命令行處理,跳過任意一步,都可能造成意料外的錯誤!

相關(guān)推薦:

JavaScript中eval的使用詳解

JavaScript中eval的使用詳解

JavaScript中eval的使用詳解

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊12 分享