2012-02-03 96 views
3

我讀從shell腳本變量的文件的字符串,並希望替換其值的變量的函數一樣殼牌解析字符串

hello.txt: 
------------- 
Hello $NAME 


a.sh 
------------- 
function printout 
{ 
    echo ???somehow_parse??? $1 
} 

NAME=Joe 
printout "$(cat hello.txt)" 
NAME=Nelly 
printout "$(cat hello.txt)" 

這個例子是不是最好的,但它描述了我的問題。換句話說:我可以使用shell作爲模板引擎嗎?

我正在使用ksh。

+0

可能重複](http://stackoverflow.com/questions/2900707/lazy-evaluation-in-bash) – 2012-02-03 14:38:14

回答

1

一般來說,我會採用sed/awk的搜索和替換方法,如Kent's answerthis answer所示。

如果你想要一個純shell的方法,那麼標準的方法是使用eval。但是,這帶來了安全風險。例如:

[[email protected]]$ cat hello.txt 
hello $NAME; uname -a 
[[email protected]]$ NAME="shawn" 
[[email protected]]$ eval echo "`cat hello.txt`" # DO NOT DO THIS! 
hello shawn 
Linux SOMEHOST 2.6.9-101.ELsmp #1 SMP Fri May 27 18:57:30 EDT 2011 i686 i686 i386 GNU/Linux 

注意如何將命令注入到模板中!

您可以使用此方法但是降低風險:

[[email protected]]$ eval "OUT=\"`cat hello.txt`\"" 
[[email protected]]$ echo $OUT 
hello shawn; uname -a 

請注意,這仍然不是萬無一失爲命令仍然可以使用$(cmd)`cmd`注入。

總之,只有在瞭解風險並可以控制/限制對模板文件的訪問時,才應該使用eval

這裏有一個如何這可以在腳本中應用的例子:

function printout { 
    FILENAME=$1 
    eval "OUT=\"`cat $FILENAME`\"" 
    echo $OUT 
} 

NAME=Joe 
printout hello.txt 
NAME=Nelly 
printout hello.txt 
+0

這個'eval'就是我想要的。這肯定是有風險的,但我腳本的唯一用戶是我。如果我是一個傻瓜,對我感到羞恥。 – torbatamas 2012-02-03 14:42:36

0

是什麼?

kent$ head hello.txt t.sh 
==> hello.txt <== 
hello $name 

==> t.sh <== 
#!/bin/bash 

function printout 
{ 
    echo $1|awk -v name="$name" 'gsub(/\$name/,name)' 
} 
name=xxx 
printout "$(cat hello.txt)" 
name=yyy 
printout "$(cat hello.txt)" 

運行:

kent$ ./t.sh 
hello xxx 
hello yyy 
1

如果你確定你的模板文件中的內容是完全安全的,也就是說,它不包含字符串來執行任何可能損害命令你的電腦,那麼你可以使用eval

#!/bin/bash 
NAME=Joe 
TEMPLATE=$(cat hello.txt) 
eval "echo $TEMPLATE" 
NAME=Nelly 
eval "echo $TEMPLATE" 

輸出示例:

HELLO Joe 
HELLO Nelly 
0

我認爲最簡單的方法是使用basename實用。

舉例來說,如果你有以下字符串:a='/home/you/stuff/myfile.txt'你可以使用這樣的命令:

dirname $a 
basename $a 
basename $a .txt 

,並得到輸出,看起來像這樣:

/home/you/stuff 
myfile.txt 
myfile 
中的Bash [懶惰的評價