Text-Processing
awk 列印除匹配之前的所有行
我有這個文件
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
,導致腳本在列印最後一行。