2013-01-21 33 views
11

考慮一個ASCII文本文件(可以說裏面含有非shell腳本語言的代碼):如何擴展文本文件中的shell變量?

Text_File.msh:

spool on to '$LOG_FILE_PATH/logfile.log'; 
login 'username' 'password'; 
.... 

現在,如果這是一個shell腳本,我可以運行它因爲$ sh Text_File.msh和shell會自動擴展變量。 我想要做的是有shell擴展這些變量,然後創建一個新的文件Text_File_expanded.msh如下:

Text_File_expanded.msh:

spool on to '/expanded/path/of/the/log/file/../logfile.log'; 
login 'username' 'password'; 
.... 

考慮:

$ a=123 
$ echo "$a" 
123 

所以技術上來說這應該是訣竅:

$ echo "`cat Text_File.msh`" > Text_File_expanded.msh 

...但它不能按預期工作,並且輸出文件與源相同。

所以我不確定如何做到這一點..我的目標是更容易維護嵌入在我的非shell腳本中的目錄路徑。 這些腳本不能包含任何UNIX代碼,因爲它不是由UNIX shell編譯的。

+1

您的變量是否在單引號內,如上所示? – Guru

+0

@Guru - 目前,它在文本文件中是單引號或沒有周邊引號。 –

+1

相關問題:http://superuser.com/q/235738/126693 –

回答

8

此解決方案不是優雅的,但它的工作原理。創建一個腳本調用shell_expansion.sh:

echo 'cat <<END_OF_TEXT' > temp.sh 
cat "$1"     >> temp.sh 
echo 'END_OF_TEXT'  >> temp.sh 
bash temp.sh >> "$2" 
rm temp.sh 

然後,您可以調用該腳本如下:

bash shell_expansion.sh Text_File.msh Text_File_expanded.msh 
+0

謝謝@Hai Vu。我首先設置變量'$ LOG_FILE_PATH =/some/path'然後運行'$ ./shell_expansion.sh Text_File.msh Text_File_expanded.msh'(還有'$ bash shell_expansion.sh Text_File.msh Text_File_expanded.msh') - 但是Text_File_expanded.msh $ LOG_FILE_PATH條目被替換爲空白空格。我可能是這樣做不正確.. –

+1

我沒有'出口'變量..我試過'$ export LOG_FILE_PATH =/SONE /路徑/'它工作正常。謝謝! :) –

+0

超酷的想法! – anishsane

9

如果一個Perl的解決方案是確定你:

示例文件:

$ cat file.sh 
spool on to '$HOME/logfile.log'; 
login 'username' 'password'; 

解決方案:

$ perl -pe 's/\$(\w+)/$ENV{$1}/g' file.sh 
spool on to '/home/user/logfile.log'; 
login 'username' 'password'; 
+0

謝謝@Guru - 我試了一下,它工作正常..因爲我需要避免依賴於Perl我不能應用此解決方案。我不是Perl專家,但是我們確定'\ w'將始終正確捕獲shell變量名稱。 –

+0

好吧我瞪了一眼,得到了我的答案 - 1. [PERL參考](http://www.troubleshooters.com/codecorn/littperl/perlreg.htm):\ w將匹配「字」字符(字母數字加「_」 )。 2. [UNIX shell參考](http://www.tutorialspoint.com/unix/unix-using-variables.htm): 變量的名稱只能包含字母數字字符和「_」。 –

+1

@KentPawar:你說得對。 – Guru

8

上述答案的一個侷限是它們都需要將變量導出到環境中。以下是我想出了將允許變量是本地的當前shell腳本:

#!/bin/sh 
FOO=bar; 
FILE=`mktemp`; # Let the shell create a temporary file 
trap 'rm -f $FILE' 0 1 2 3 15; # Clean up the temporary file 

(
    echo 'cat <<END_OF_TEXT' 
    cat "[email protected]" 
    echo 'END_OF_TEXT' 
) > $FILE 
. $FILE 

上面的例子允許變量$FOO在命令行指定的文件來代替。我相信它可以得到改善,但這對我來說至今還是有效的。

感謝他們的想法以前的答案!

+0

謝謝@PaulGear!歡迎來到StackOverflow。 +1使用「陷阱」清理臨時文件。我已經提出了一些編輯,以使像我這樣的新手更容易理解代碼;請審查編輯並在需要時恢復它們。謝謝 –

+0

我沒有得到'0'指的是哪個信號。 –

+2

0表示正常退出而非信號。 –

1

如果你想翻譯是已知的,數量有限的變量,你總是可以做翻譯自己:

sed "s/\$LOG_FILE_PATH/$LOG_FILE_PATH/g" input > output 

而且還假設變量本身是已知的

7

如果你想讓它在一行(我不是一個bash的專家,所以有可能是警告此,而是作品無處不在我已經試過了):

時的test.txt包含

${line1} 
${line2} 

則:

>line1=fark 
>line2=fork 
>value=$(eval "echo \"$(cat test.txt)\"") 
>echo "$value" 
line1 says fark 
line2 says fork 

顯然,如果你只是想打印出來就可以取出多餘的value=$()echo "$value"

+0

如果'test.txt'包含,例如,'; touch/etc/your_system_is_pwned; echo「'你會看到不好的事情發生。 – Wildcard

11

這個問題已經被問在另一個線程,這是最好的答案IMO:

export LOG_FILE_PATH=/expanded/path/of/the/log/file/../logfile.log' 
cat Text_File.msh | envsubst > Text_File_expanded.msh 

如果在Mac上,安裝gettext第一:brew install gettext

見: Forcing bash to expand variables in a string loaded from a file

0

創建ascii文件test.txt包含以下內容:

Try to replace this ${myTestVariable1} 
bla bla 
.... 

現在創建「sub.sed」含有變量名的文件,例如

's,${myTestVariable1},'"${myTestVariable1}"',g; 
s,${myTestVariable2},'"${myTestVariable2}"',g; 
s,${myTestVariable3},'"${myTestVariable3}"',g; 
s,${myTestVariable4},'"${myTestVariable4}"',g' 

打開終端移動到含有的test.txt和sub.sed的文件夾。
定義varible的價值被替換

myTestVariable1=SomeNewText 

現在打電話sed將替換可變

sed "$(eval echo $(cat sub.sed))" test.txt > test2.txt 

輸出將是

$cat test2.txt 

Try to replace this SomeNewText 
bla bla 
.... 
0

該解決方案可以讓你保持輸出文件中格式相同

複製並粘貼到你的腳本中的以下行

cat $1 | while read line 
do 
    eval $line 
    echo $line 
    eval echo $line 
done | uniq | grep -v '\$' 

這將改爲由行參數行,然後處理通過嘗試和打印的每一行兩次文件: - 與替代一次 - 一旦沒有取代 變量。 然後刪除重複行 然後刪除包含可見變量的行($)