Shell指令碼之:EVAL and EXEC command

來源:互聯網
上載者:User

標籤:linux shell eval exec bash script


    由於工作上的需要,花了點時間,研究了一下eval和exec這兩個shell內建特殊的命令。因為用的不是很多,所以還是有一點比較隱晦的。。


1.eval                  

    該命令是bashshell中內建的一個命令,相比其他的命令來說還是有一點的難度。該命令後面所跟的內容都認為是參數,但是會兩次掃描其參數,第一次掃描會將參數中的變數進行替換,第二
次掃描會將後面的參數當作一個shell中的命令組合來執行命令。其常用的情況是對變數的處理
下面看幾個例子:


案例1:直接組合命令
[[email protected] shellscripts]# eval ls -l /home/shellscripts/
total 8
-rwxr-xr-x 1 root root 71 Sep  9 13:29 1.sh
-rwxr-xr-x 1 root root 83 Sep  9 13:17 test.sh
[[email protected] shellscripts]# ls -l /home/shellscripts/
total 8
-rwxr-xr-x 1 root root 71 Sep  9 13:29 1.sh
-rwxr-xr-x 1 root root 83 Sep  9 13:17 test.sh
[[email protected] shellscripts]#
從上面的資訊可以看出,當eval後面直接跟原生參數時,直接當作命令來執行,此時的執行結果,跟在shell中直接執行命令沒有任何區別

案例2:替換變數
寫如下一個腳步:
[[email protected] shellscripts]# cat 1.sh
#!/bin/bash
dirpath=/home/shellscripts
cmd="ls -l $dirpath | awk -F ‘ ‘ ‘{print \$9}‘"
eval $cmd
[[email protected] shellscripts]#
[[email protected] shellscripts]# ./1.sh

1.sh
test.sh
[[email protected] shellscripts]# ls -l /home/shellscripts/ | awk -F ‘ ‘ ‘{print $9}‘

1.sh
test.sh
[[email protected] shellscripts]#

從上面的資訊可以看出最終的執行結果和在命令列直接執行命令的結果是一致的,那也就是說eval執行$cmd的時候,第一次先將變數$cmd用其值替換了,第二次將變數$cmd的值直接在shell中以命令的形式來執行。

註:在上面的指令碼中,相信你應該能注意到\$9,為什麼要加個轉意字元(\),如果不加的話會被當作位置變數進行替換

案例3:可以執行任何值為命令組合的變數
先看例子:
[[email protected] shellscripts]# cat 1.sh
#!/bin/bash
dirpath=/home/shellscripts
cmd="ls -l $dirpath | awk -F ‘ ‘ ‘{print \$9}‘"
#eval $cmd     /注釋掉該行
$cmd
[[email protected] shellscripts]#

上面的指令碼中,注釋掉了eval所在行,直接調用$cmd變數,看起來變數cmd的值是一個shell中的命令組合,似乎應該可以正常運行,好運行一下:
[[email protected] shellscripts]# ./1.sh
ls: cannot access |: No such file or directory
ls: cannot access awk: No such file or directory
ls: cannot access ‘: No such file or directory
ls: cannot access ‘: No such file or directory
ls: cannot access ‘{print: No such file or directory
ls: cannot access $9}‘: No such file or directory
/home/shellscripts:
total 8
-rwxr-xr-x 1 root root 103 Sep  9 13:52 1.sh*
-rwxr-xr-x 1 root root  83 Sep  9 13:17 test.sh*
[[email protected] shellscripts]#

額,看到沒,報錯了,除了識別了ls -l $dirpath的部分 ,管道符之後的內容一概為識別。但是從案例2中,可知使用eval $cmd的時候,就可以很好的執行。

從案例2和案例3的對比,可以知道,在實際使用中,可以將任意組合的命令賦值給一個變數,然後在需要的位置通過eval $variable來執行這個命令。試想如果你遇到了一個很複雜的命令組合,
可能在多個地方需要執行,此時使用eval的功能就很方便。當然,有人可能會說可以使用函數,但是函數只有在調用的時候才會生效,且每次調用都要到記憶體中執行一遍,變數一旦賦值,直到變數的生命週期結束都會存在內層中供其調用。


案例4:變數替換賦值
看例子:
建立一個腳步如下:
[[email protected] shellscripts]# cat 2.sh
#!/bin/bash
x=100
y=x
eval echo \$$y
eval $y=50
echo $x
eval echo \$$y
[[email protected] shellscripts]#

執行腳步看結果:
[[email protected] shellscripts]# ./2.sh
100
50
50
[[email protected] shellscripts]#

分析:從上面的結果看,腳步返回了三個值。指令碼運行時,先對x變數進行賦值,然後對y變數進行賦值,接著執行eval echo \$$y,返回了一個100,到這裡還可以理解。接著執行eval $y=50,然
後嘗試著輸出$x的值,發現輸出了一個50。一開始x變數的值是100,這裡卻變成了50 why?原因就在eval $y=50這句話,這句話相當於一個變數賦值,$y替換成x而將50賦值給了x變數,因此x
變成了50,而最後一句話再次執行eval \$$y驗證其結果,發現確實變成了50。。。


2.exec
    exec也是shell內建的一個命令。類似與eval,source,但是不同的是exec執行後面的命令後會替換當前的shell進程,而前兩者不會。。關於exec的用法確實有點特殊,可能編程的人士會對
其比較熟悉,這裡介紹三種比較常見的用法;

用法一:用來分離執行指令碼,並退出子指令碼的shell進程
主指令碼:
[[email protected] shellscripts]# cat main.sh
#!/bin/bash
bash /home/shellscripts/3.sh
ls -al
[[email protected] shellscripts]#

子指令碼:
[[email protected] shellscripts]# cat 3.sh
#!/bin/bash
ls -l /etc | head -n 5
exec echo "this is a test"
echo "hello world"
[[email protected] shellscripts]#

執行主指令碼,看結果:
[[email protected] shellscripts]# ./main.sh
total 1252
-rw-r--r--.  1 root root     44 Sep  5 18:13 adjtime
-rw-r--r--.  1 root root   1512 Jan 12  2010 aliases
-rw-r--r--.  1 root root  12288 Sep  2 09:24 aliases.db
drwxr-xr-x.  2 root root   4096 Sep  2 11:57 alternatives
this is a test
total 44
drwxr-xr-x  2 root root 4096 Sep  9 15:51 .
drwxr-xr-x. 3 root root 4096 Sep  9 14:19 ..
-rwxr-xr-x  1 root root  103 Sep  9 13:52 1.sh
-rwxr-xr-x  1 root root   71 Sep  9 14:02 2.sh
-rwxr-xr-x  1 root root   81 Sep  9 15:51 3.sh
-rwxr-xr-x  1 root root   92 Sep  9 15:43 4.sh
-rwxr-xr-x  1 root root   31 Sep  9 15:16 5.sh
-rwxr-xr-x  1 root root   72 Sep  9 15:43 6.sh
-rw-r--r--  1 root root   41 Sep  9 15:12 file
-rwxr-xr-x  1 root root   49 Sep  9 14:32 main.sh
-rwxr-xr-x  1 root root   83 Sep  9 13:17 test.sh
[[email protected] shellscripts]#

分析:
    從上面的指令碼輸出資訊可以看到成功調用了3.sh指令碼,但是你會發現3.sh指令碼中的最後一行沒有執行,因為沒有輸出內容。這是因為在輸出了exec後面的命令執行結果後,就清除了3.sh腳步
開啟的子shell進程,而後回到主shell進程繼續執行後面的內容。。

這個特性似乎看起來沒多大用處,有人說直接寫在一個腳步裡好了。但是對於複雜的環境,避免幹擾,或許你需要這樣的用法。。

用法二:用來設定描述符重新導向輸入檔案內容
指令碼如下:
[[email protected] shellscripts]# cat 4.sh
#!/bin/bash
exec 3</home/shellscripts/file
while read -u 3 str
do
echo $str
done
exec 3<&-

建立/home/shellscripts/file檔案:
[[email protected] shellscripts]# cat file
hello world haha a b c
liuxueming
liwei
[[email protected] shellscripts]#

執行指令碼,看結果:
[[email protected] shellscripts]# ./4.sh
hello world haha a b c
liuxueming
liwei
[[email protected] shellscripts]#

從上面的執行結果看,正常的輸出了文本的內容,且按照while迴圈的次序輸出。這裡要解釋的是檔案描述符。exec可以實現檔案描述符的重新導向,將某個檔案描述符關聯到某個檔案,以後對此
檔案描述符的操作就是對該檔案的操作,這也符合linux系統檔案描述符的定義。例如上面的腳步將3重新導向輸入到/home/shellscripts/file檔案,這樣在下面就可以使用read -u 3來指定該描述
符,否則read後面不可以直接添加檔案。當調用完成後,還要關閉檔案描述符,例如上面的exec 3<&-

當然這裡還可以使用另外一種方法:
while read str
do
echo $str
done < /home/shellscripts/file




用法三:用來設定描述符重新導向輸出內容至檔案
看實驗:
[[email protected] fd]# pwd
/dev/fd
[[email protected] fd]# ls
0  1  2  255
[[email protected] fd]# exec 4>/home/shellscripts/test
[[email protected] fd]# ls -l /etc | head -n 5 > 4
[[email protected] fd]# exec 4>&-
[[email protected] fd]# cat /home/shellscripts/test
total 1252
-rw-r--r--.  1 root root     44 Sep  5 18:13 adjtime
-rw-r--r--.  1 root root   1512 Jan 12  2010 aliases
-rw-r--r--.  1 root root  12288 Sep  2 09:24 aliases.db
drwxr-xr-x.  2 root root   4096 Sep  2 11:57 alternatives

看到沒,重新導向輸出到檔案描述符4的內容,都被輸出到檔案:/home/shellscripts/test中了。。。


結束!!!

    笨蛋的技術------不怕你不會!!!


本文出自 “笨蛋的技術” 部落格,請務必保留此出處http://mingyang.blog.51cto.com/2807508/1550281

Shell指令碼之:EVAL and EXEC command

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.