Awk

awk 無法處理 sed 的管道輸出

  • September 23, 2021

我有一個大致如下所示的日誌文件:

Sep 23 10:28:26 node kernel: em0: device is going DOWN
Sep 23 10:28:26 node kernel: em0: device is going UP
Sep 23 10:29:14 node cdsmon: /tmp/instance0 ; core dumped
Sep 23 10:29:14 node cdsmon: /tmp/instance0 ; core dumped
Sep 23 10:28:26 node kernel: em0: device is going DOWN
Sep 23 10:29:14 node cdsmon: /tmp/instance1 ; core dumped
Sep 23 10:28:26 node kernel: em0: device is going UP
Sep 23 10:29:14 node cdsmon: /tmp/instance2 ; core dumped

我想用 檢測線條,cdsmon然後將線條分割;(以獲取/tmp/instance0和 之類的事件core dumped)。

為此,我用作sed

sed -u -n -e "s/^.*cdsmon: //p" /tmp/dev.log

輸出為:

/tmp/instance0 ; core dumped
/tmp/instance0 ; core dumped
/tmp/instance1 ; core dumped
/tmp/instance2 ; core dumped

但是在將這個輸出傳送到awk如下所示時,它會給出與上面相同的輸出:

sed -u -n -e "s/^.*cdsmon: //p" /tmp/dev.log | awk -F ";" "{print $1}"

儘管-used.

誰能指出我是否遺漏了什麼?我正在使用帶有正常 awk/sed 的 FreeBSD 機器,不幸的是無法安裝任何新軟體包。

的行為的原因awk是您已將程序括在引號中,這使字元串對 shell 的變數擴展開放。這意味著您執行程序的 shell 將首先展開$1,並且由於這可能是未定義的,它會展開為空字元串。

所以,你的程序相當於

awk -F ";" "{print}"

這就是列印整行的原因。這是您應該始終將awk(and sed) 程序包含在引號中的原因之一。

請注意,在大多數情況下,您不需要將輸出從管道輸入,sed反之亦然awk。在您的範例中,如果您想獲取“事件標籤”之後的第一個欄位,您可以執行以下操作:

sed -E -n 's/^.*cdsmon: ([^;]*).*$/\1/p' /tmp/dev.log 

這將圍繞字元串定義一個擷取組cdsmon:,直到 first ;,並將整行替換為該擷取組的內容。

如果要列印由 記錄的事件的摘要cdsmon,可以將上述sed方法擴展為:

sed -E -n 's/^.*cdsmon: ([^;]*) ; (.*)$/\1 : \2/p' dev.log 

或者,這是另一種awk-only 方法:

awk -F'(cdsmon: | ; )' 'NF==3{printf "%s : %s\n",$2,$3}' dev.log 

對於您的範例,兩者都將列印

/tmp/instance0 : core dumped
/tmp/instance0 : core dumped
/tmp/instance1 : core dumped
/tmp/instance2 : core dumped

但請注意,該awk方法可能會遇到極端情況。它採用模式cdsmon:;作為欄位分隔符。當有三個欄位時(在您的範例中,它只能發生在cdsmon:條目中),它會列印第二個和第三個欄位,對應於實例名稱之後cdsmon:和原因之後;

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