Text-Processing

awk 列印除匹配之前的所有行

  • September 8, 2022

我有這個文件

john
robert
rose*
ann*
charles
david
liz*
louis
wendy*
kate*
mandy*
paul

我想列印除“*”之前的那些行之外的所有行,所以所需的輸出是:

john
rose*
ann*
charles
liz*
wendy*
kate*
mandy*
paul

我試過:

awk '/\*/ {f=1}; (!f &&NR > 1) {print p}; {p=$0;f=0} END {print p}' file

它生成輸出

john
ann*
charles
liz*
mandy*
paul

程式碼有什麼問題?

rose**( ann*) 之前的一行,因此您的標準I want to print all lines except those lines before '*'與您的預期輸出不匹配,並且您的程式碼似乎按照您所說的去做。

改為列印所有包含*和/或不包含的行的行,*從而獲得您顯示的預期輸出:

$ awk '(NR>1) && ((p ~ /\*/) || (!/\*/)){print p} {p=$0} END{print p}' file
john
rose*
ann*
charles
liz*
wendy*
kate*
mandy*
paul

這主要是為了我個人的享受。

解決相同問題的sed命令:

sed -e 'N' -e '/[^*]$/P' -e '/[*]\n.*[*]$/P' -e '$!D' -e 's/.*\n//' file

這保留了編輯緩衝區中輸入的兩行。下一行使用 , 添加到編輯緩衝區N,並由 插入的文字換行符與現有數據分隔sed

如果緩衝區末尾沒有*,則緩衝區的初始部分將列印為P. 如果一條非星號線跟隨它,這就是輸出一條線。

如果緩衝區包含 a*後跟文字換行符(即緩衝區的第一部分以 a 結尾*並且緩衝區末尾有a *;然後第一部分用 列印P。這就是輸出一條星號線的內容,即使另一條星號線緊隨其後。

D除非我們到達末尾,否則刪除緩衝區的初始部分。該D命令還自動使腳本從第一條指令開始(但不會清空整個編輯緩衝區或自動讀取另一行輸入,就像d這樣做的那樣)。

如果我們到達最後的s命令,我們已經讀取了最後一行,最後兩行在緩衝區中。其中第一個應該已經列印(或沒有),所以我們只需要確保在允許列印剩餘的最後一行之前刪除它。

更短的變體:

sed -e '$q' -e 'N' -e '/[^*]$/P' -e '/[*]\n.*[*]$/P' -e 'D' file

這依賴於這樣一個事實,即最後的無條件D命令也會剪掉保存在編輯緩衝區中的倒數第二行,並且我們接受最終迭代,該迭代在腳本開頭被縮短$q,導致腳本在列印最後一行。

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