[英]Using bash for loop variable within awk print
我試圖了解bash和awk中的具體情況:
我想使用awk 二元運算符將兩個變量 (空格) 之間的字符串連接作為變量迭代, $i
,在bash for循環中:
$ for i in ' '; do
echo "foo bar" | awk '{print $1$i$2}'
done
foofoo barbar
預期產量為: foobar
$ $SHELL --version | head -n1
GNU bash, version 4.3.42(4)-release (x86_64-unknown-cygwin)
$ awk --version | head -n1
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.3, GNU MP 6.1.0)
全面測試
$ for i in '+' '-' '*' '/' '%' ' ' ''; do echo "2.0 4.0" | awk '{print $1$i$2}'; done
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
2.02.0 4.04.0
這似乎有點棘手。 實際上它打印foo
, foo bar
和bar
。 因為i
的值沒有在awk中定義(它是一個bash變量),所以它被認為是$0
(我不知道這種行為,但它有意義)。
稍微改變一下代碼
for i in ' '; do
echo "foo bar" | awk '{print $1"<"$i">"$2}'
done
輸出:
foo<foo bar>bar
如果要傳遞變量i
的值,可以使用-v
參數。 但$i
不會起作用,因為i
的值應該是$i
的數字,所以只需使用簡單的i
。
for i in ' '; do
echo "foo bar" | awk -v i="$i" '{print $1"<"i">"$2}'
done
輸出:
foo< >bar
我試着把它作為評論,但是說的太多了,有些需要格式化:
@adam你似乎對awk有一些根本的誤解,這讓你難以理解你被告知的內容。 我懷疑它歸結為此 - awk不是shell 。 Awk是一個完全獨立的工具/語言,它有自己的范圍,變量,函數等。
不要試圖通過使用中間單引號(例如awk '{print $1'"$i"'$2}'
)直接在awk腳本中訪問shell變量的值,因為這會將shell變量的值轉換為解釋器之前的awk代碼讀取它並使用各種值$i
打開你的隱藏錯誤消息(或者更糟糕的是 - 沒有錯誤消息的陰險錯誤)的可怕錯誤。
你說你Cannot get -v to work even without for loop:
但是你表明它完美地工作了兩次:
$ echo "foo bar" | awk -v var=" " '{print $1var$2}'
foo bar
在上面的例子中,您將創建一個名為var
的awk變量,其中包含一個空白字符" "
。 然后打印$ 1( foo
),然后是var( " "
),然后是$ 2( bar
),輸出<foo>< ><bar>
完全應該是這樣。
在所有示例中,您將變量設置為單個空格字符,將其與其他一些值連接(例如-v var=" "
然后$1var$2
)然后由於某種原因期望空格字符不存在於輸出。
$ echo "foo bar" | awk -v var=" " '{print $1'var'$2}'
foo bar
在上面的例子中,您將創建一個名為var
的awk變量,其中包含一個空白字符" "
。 當你編寫任何用單引號括起來的shell腳本(awk,sed,grep等)時:
any_cmd 'abc'
然后你告訴cmd
解釋/執行符號引號內的內容。 您不能在單引號分隔的腳本中包含單引號 - 這是shell基礎。 所以當你寫:
any_cmd 'abc'def'ghi'
內部單引號實際上是從any_cmd
語言中any_cmd
並返回到shell來解釋,並且shell會在any_cmd
之前嘗試擴展它。 所以如果你有:
xyz=17
any_cmd 'abc'$xyz'ghi'
然后any_cmd
實際看到的解釋是:
any_cmd 'abc17ghi'
但如果你在那里有東西,shell無法擴展,那么它就會保持原樣:
and_cmd 'abc'def'ghi'
傳遞給any_cmd
:
any_cmd 'abcdefghi'
回到你的例子:
$ echo "foo bar" | awk -v var=" " '{print $1'var'$2}'
foo bar
該var
$ 1和$ 2之間將通過外殼以來的第一解釋'
圍繞IT方面正在它的awk腳本,回到殼,但那么它只是一些文字,外殼無法展開,因此上方通過awk as-is使它成為:
$ echo "foo bar" | awk -v var=" " '{print $1var$2}'
然后以迂回的方式返回到您的第一個腳本,並再次按預期輸出。
以上聽起來很復雜,但實際上非常簡單:
要在awk中連接字符串,只需將它們並排放置即可。
要將shell變量的值傳遞給awk,請使用-v
,例如awk -v awkvar="$shellvar" 'print "foo" awkvar "bar"'
。
不要試圖通過反復試驗來學習awk,而是首先閱讀Arnold Robbins的書“Effective Awk Programming”,第4版,然后再玩它。
啊,我想出了問題2 。
循環初始化:
$ for i in ' '; do echo "foo bar" | awk '{print $1$i$2}'; done
foofoo barbar
將$i
括在"
:
'{print $1$i$2}'
來
'{print $1"$i"$2}'
$ for i in ' '; do echo "foo bar" | awk '{print $1"$i"$2}'; done
foo$ibar
這導致我試圖用'
所以$i
可以正確評估來分解awk:
'{print $1"$i"$2}'
來
'{print $1'"$i"'$2}'
$ for i in ' '; do echo "foo bar" | awk '{print $1'"$i"'$2}'; done
foobar
使用解決方案測試所有awk二元運算符和null:
$ for i in '+' '-' '*' '/' '%' ' ' ''; do
echo "2.0 4.0" | awk '{print "Using binary operator \"'"$i"'\" for \""$1"\" and \""$2"\" evaluates to:\t" $1'"$i"'$2}';
done
Using binary operator "+" for "2.0" and "4.0" evaluates to: 6
Using binary operator "-" for "2.0" and "4.0" evaluates to: -2
Using binary operator "*" for "2.0" and "4.0" evaluates to: 8
Using binary operator "/" for "2.0" and "4.0" evaluates to: 0.5
Using binary operator "%" for "2.0" and "4.0" evaluates to: 2
Using binary operator " " for "2.0" and "4.0" evaluates to: 2.04.0
Using binary operator "" for "2.0" and "4.0" evaluates to: 2.04.0
注意: ''
顯然不是二元運算符,只是一個檢查。
成功!
警告:正如其他人所指出的,此解決方案不適用於一般字符串連接 。 shell變量i
應該只是awk二元運算符。 將i
設置為任何其他變量可能會導致問題。
-v
使用-v
似乎不允許二進制操作:
$ echo "2.0 4.0" | awk -v var="+" '{print $1var$2}'
2.0+4.0
輸出: 2.0+4.0
期望的輸出: 6
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.