2010-07-02 56 views
3

我有一個shell腳本構造一個awk程序作爲一個字符串,然後將該字符串傳遞給awk。這是因爲我想在awk程序中使用shell變量的值。如何預先構建awk語句以在命令行上傳遞給awk?

我的代碼如下所示:

awk_prog="'{if (\$4~/$shell_var/) print \$1,\$2}'" 
echo $awk_prog 
awk $awk_prog $FILENAME 

然而,當我把這個字符串傳給awk中,我總是得到錯誤:

'{if ($4~/regex/) print $1,$2}' 
awk: '{if 
awk:^invalid char ''' in expression 

是什麼錯誤訊息?我試過-F:開關,但它沒有幫助。我怎樣才能解決這個問題?

謝謝。

回答

5

這是由shell引用引起的。下面的工作:

awk_prog="{ if (\$4 ~ /$shell_var/) print \$1, \$2 }" 
echo "$awk_prog" 
awk "$awk_prog" $FILENAME 

當你在命令行中運行awk '{ print }' foo,外殼解釋等AWK接收兩個參數刪除程序周圍的報價 - 首先是程序文本和第二個是文件名foo。你的例子是發送awk程序文本'{if ...}',就awk而言,這是無效的語法。外部引號不應該存在。

在上面給出的代碼片段中,shell使用awk_prog=行中的引號將字符串的內容分組爲一個值,然後將其分配給變量awk_prog。當它執行awk "$awk_prog"...行時,必須引用$awk_prog的擴展,以便awk將程序文本作爲單個參數接收。

4

還有另一種方式來獲得你的shell變量到awk的 - 使用awk的-v選項:如果

awk -v pattern="$shell_var" '$4 ~ pattern {print $1, $2}' "$FILENAME" 

使用-v多次,你有幾個變量傳遞給AWK。

如果你真的想在一個shell變量來保存你的awk程序,構建它使用printf

awk_script="$(printf '$4 ~ /%s/ {print $1, $2}' "$shell_var")" 
awk "$awk_script" "$FILENAME" 

注意使用printf命令引號:單引號括起來的模板,以保護美元您希望awk解釋的標誌,用於shell變量的雙引號。

1

另一個(我認爲)解決你直覺上試圖做的(IMO簡單)解決方案只是使用eval。您希望殼的行爲就好像你從字面上鍵入:

 
awk '{if ($4~/foo/) print $1,$2}' path 

(其中foo和路徑是$ shell_var和$文件名的文字內容)。要做到這一點,只需在最後一行的前面打一個eval(也許引號是好的措施,但在這種情況下它們不是必需的),以便您的最後一行是:

 
eval "awk $awk_prog $FILENAME"