Awk

如何在 awk if 語句中使用星號

  • October 25, 2022

我有一個場景,我需要列印一行,但是如果使用 awk 來搜尋一個數字,則會附加一個帶有更多數字的雙冒號:

請參見下面的範例:

test1 test2 37:375003 test3 test4
test1 test2 38:375004 test3 test4
test1 test2 39:375005 test3 test4
test1 test2 40:375006 test3 test4
test1 test2 41:375007 test3 test4

我想要實現的是使用如下命令:

cat test_out.txt | awk "{if ($3 == 37~/\:*/ ) print $0;}"

以上應該給我以下行:

test1 test2 37:375003 test3 test4

得到以下語法錯誤:

Syntax Error The source line is 1.
The error context is
            {if ( >>>  == <<<
awk: 0602-502 The statement cannot be correctly parsed. The source line is 1.

您需要使用~二元運算符,其語法為:

string ~ regexp

要將字元串與正則表達式匹配,因此:

<test_out.txt awk '$3 ~ /^37:[[:digit:]]+$/'

列印第三個欄位與擴展正則表達式匹配的記錄(預設操作的{print}縮寫)。{print $0}``^37:[[:digit:]]+$

在 ERE 語法中:

  • ^在主題的開頭匹配
  • [...]: 匹配集合中的任何字元或排序元素。
  • [:digit:]在上面的集合中表示在區域設置中分類為十進制數字的任何字元(在大多數係統上,僅限於 0123456789)。更改為0123456789in mawkwhich 不支持那些 POSIX 字元類,或者如果您不想匹配其他十進制數字。0-9也可以工作,mawk但也可以在某些awk實現中匹配其他字元。
  • +是針對前面的一個或多個。所以這裡有一個或多個數字
  • $匹配在主題的末尾。

如果您不關心後面的部分37:是否由數字組成,那麼正則表達式只是^37:37:在主題的開頭)。

另一種方法是:

<test_out.txt awk '$3 + 0 == 37'

數字+ 0運算強制awk嘗試轉換$3為數字,忽略初始數字之後的任何內容。然後這將匹配37:anything,但也匹配37.0;whatever¹,3.7e+1¹,可能0x25#xxx與某些awk實現,+37+38+$3 == 37雖然使用標準,但不適用於某些awk實現。

37對於來自 shell 變數的值(此處),您可以在 shell 中構造正則表達式並awk通過ENVIRONment 變數將其傳遞給:

var=37
ERE='^'$var':[[:digit:]]+$' <test_out.txt awk '$3 ~ ENVIRON["ERE"]'

或者awk v從 shell 變數中創建一個變數²:

var=37
<test_out.txt awk -v n="$var" '$3 ~ "^" n ":[[:digit:]]+"'

避免將 shell 變數擴展到awk程式碼中,如下所示:

<test_out.txt awk '$3 ~ /^'"$var"':[[:digit:]]+$/'

因為這通常會引入命令注入漏洞(最嚴重的漏洞類型)。

對您的嘗試的一些評論:

  • 正如@RudyC已經指出的那樣,您在 awk 程式碼周圍使用了雙引號。Shell 在其中執行參數擴展,因此$3將擴展為 shell 腳本的第三個參數的值,以及腳本$0的名稱。
  • $3 == 37 ~ /\:*/. ==的優先級高於~。就是這樣($3 == 37) ~ /\:*/。這就是將正則\:*表達式與該比較的結果相匹配(1 或 0,取決於是否$3為 37)
  • \:*因為正則表達式未指定,因為\:未指定。要匹配文字:,它是:單獨的。:*將是 0 或更多:s 所以匹配任何東西,因為任何字元串都包含至少 0 :s。*在正則表達式中匹配 0 個或多個先前的事物。*您可能會將其與匹配 0 個或更多字元的 shell 萬用字元混淆。在正則表達式中,0 個或多個字元是.*.是匹配單個字元的運算符。
  • awk語句的形式為condition {action},其中條件動作都可以省略。在您的情況下,您省略了條件if操作中使用,而使用{print $0}恰好是預設操作。雖然這很有效,但對使用者來說這將非常awk謹慎awk
  • 您過去cat常常cat合併一個幾乎沒有意義的文件。shell 可以自己打開文件,使其成為awk使用重定向的標準輸入,從而節省了程序和通過管道推送內容的需要。您還可以將文件名作為參數傳遞給awk它也可以自己打開它。

¹假設十進制基數字元在語言環境中.而不是,在語言環境中,至少對於某些awk實現,例如awkPOSIX 模式下的 GNU。

² 請注意會-v破壞反斜杠,因此ENVIRON在一般情況下使用更安全。

引用自:https://unix.stackexchange.com/questions/722327