在 awk 中使用 shell 變數
這是我的腳本(查找包含指定模式的文件):
find . -type f \ -exec awk -v vawk="$1" '/'"$vawk"'/ {c++} c>0 { print ARGV[1]; exit 0 } END { if (! c) {exit 1}}' \{\} \;
我想將我的腳本與參數 § 一起使用:
MyScript.sh pattern
我的問題是我無法將
$1
變數放入awk
.當我嘗試調試我的腳本時
bash -x MyScript.sh pattern
這是輸出:
+ find . -type f -exec awk -v vawk=pattern '// {c++} c>0 {print ARGV[1] ; exit 0 } END { if (! c) {exit 1}}' '{}' ';'
該
$vawk
變數似乎為空。任何想法?
您似乎混淆了 awk 變數和 shell 變數。
awk -v vawk="$1"
創建一個名為 的awk變數vawk
,但您正在嘗試使用shell語法 ($vawk
)。這不起作用,因為 shell 沒有名為vawk
. 我想你想要的是awk -v vawk="$1" '$0 ~ vawk { c++ } # ...' # ^ awk variable syntax
從這個現在關閉為重複的問題轉載,因為它包括關於 awk 變數傳遞的限制的警告,人們可能會覺得這很有用。
shell 變數就是這樣:一個shell變數。如果你想把它變成一個awk變數,你需要這樣的語法:
awk -v x="$x" '$2 == x {print $1}' infile
要麼
awk '$2 == x {print $1}' x="$x" infile
但是,它們會遇到一個問題:轉義序列在其中被擴展(在 GNU
awk
4.2 或更高版本中,如果$x
以 開頭@/
和結尾/
,它被視為變數的正則表達式類型)。因此,例如,如果 shell 變數包含兩個字元反斜杠和n,則 awk 變數最終將包含換行符(在 gawk 4.2+ 中,如果它包含
@/foo/
,則 awk 變數將包含foo
並且類型為regexp
)。另一種方法(但
-v
需要 POSIX awk 或 nawk (與 1970 年代的 awk 相比,仍然可以/bin/awk
在 Solaris 中找到))是使用環境變數:x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile
另一種方法(仍然使用較新的 awk)是在 awk 中使用 ARGV 數組:
awk 'BEGIN {x = ARGV[1]; delete ARGV[1]} $2 == x {print $1}' "$x" infile
另請注意,無論您使用
ARGV
/ENVIRON
/-v
或var=value
參數,如果相應的字元串形狀像數字,則將其視為數字字元串(可辨識的數字格式的範圍因實現而異)。這很重要,因為在上面的例子中,如果是例如or ,
$2 == ENVIRON["VAR"]
它將是一個字元串比較¹ ,但是如果它是or (或者可能, 取決於實現和版本),它將是一個數字比較,假設看起來也是數字的。所以,並且都被認為是平等的。$VAR``foo``1f2``1e2``1.1``inf``0xff``awk``$2``10.0e1``100``1e2
正在做:
awk 'BEGIN {var = "" ENVIRON["VAR"]}'
將確保
var
awk
變數始終被視為字元串,即使$VAR
shell 變數看起來像一個數字。awk 'BEGIN {var = 0 + ENVIRON["VAR"]}'
將其轉換為數字(至少可以解釋為數字的前導部分)。
¹或
strcoll()
與某些實現進行比較(POSIX曾經要求),也就是說,a == b
如果其中一個a
或b
兩個是字元串,則如果a
並且b
具有相同的排序順序,則返回true。