天天看點

``和$()的差別及eval詳解

指令替換

在bash中,$( )與` `(反引号)都是用來作指令替換的。

指令替換與變量替換差不多,都是用來重組指令行的,先完成引号裡的指令行,然後将其結果替換出來,再重組成新的指令行。

eg:

``和$()的差別及eval詳解

$( )與``

在操作上,這兩者都是達到相應的效果,但是建議使用$( ),理由如下:

  1. ``很容易與”搞混亂,尤其對初學者來說。
  2. 在多層次的複合替換中,``必須要額外的轉義字元處理(反斜線),而$( )比較直覺。
  3. 最後,$( )的弊端是,并不是所有的類unix系統都支援這種方式,但反引号是肯定支援的。

eval指令

eval可以讀取一連串的參數,然後按照參數特性來執行。參數數目不限,彼此之間用分号隔開。

eval會對後面的指令進行兩遍掃描

如果第一遍掃描後,指令是個普通指令,則執行此指令;如果指令中含有變量的間接引用,則保證間接引用的語義。也就是說,eval指令将會首先掃描指令行進行所有的置換,然後再執行該指令。

是以,eval指令适用于那些一次掃描無法實作其功能的變量。

eval 執行以下兩個步驟:

第一步,執行變量替換,類似與C語言的宏替代;

第二步,執行替換後的指令串。

下面來看幾個例子:

例:執行含有帶字元串的指令

[root@localhost ~]# cat test
Hello World!
[root@localhost ~]# WORD="cat test"
[root@localhost ~]# echo $WORD
cat test
[root@localhost ~]# eval $WORD
Hello World!      

看上面的例子,把cat test指派給變量WORD。當我們執行echo WORD就是将變量WORD的值列出來,并不能得到test中的内容;然而eval WORD則能顯示檔案中的内容,因為eval指令對後面的指令進行了兩次掃描,第一次将WORD替換為 cat test,第二次執行cat test。

這些需要進行兩次掃描的變量有時被稱為複雜變量。

eval指令不僅可以回顯複雜變量,也可以用于回顯簡單變量。

例:回顯簡單變量

[root@localhost ~]# NAME=filename
[root@localhost ~]# echo $NAME
filename
[root@localhost ~]# eval echo $NAME
filename      

例:擷取傳給shell的最後一個參數

之前我們已經了解過shell文法,知道最後一個參數是$#,看如下代碼,用eval可得到其内容。

[root@localhost ~]# cat test.sh
#!/bin/bash
echo "\$$#"

eval echo "\$$#"
[root@localhost ~]# chmod u+x test.sh
[root@localhost ~]# ./test.sh first last
$2
last      
[root@localhost ~]# cat file
NAME ZHANG
AGE 20
SEX NV
[root@localhost ~]# cat test.sh
#!/bin/bash

while read KEY VALUE
do
    eval "${KEY}=${VALUE}"
done < file
echo "$NAME $AGE $SEX"
[root@localhost ~]# ./test.sh
ZHANG 20 NV