[英]How to delete all the lines after the last occurence of pattern?
我想刪除模式最后一次出現后的所有行,除了模式本身
文件.txt
honor
apple
redmi
nokia
apple
samsung
lg
htc
file.txt 我想要什么
honor
apple
redmi
nokia
apple
我試過的
sed -i '/apple/q' file.txt
這將刪除第一次出現模式后的所有行 -
honor
幾乎不使用內存的簡單、健壯的 2-pass 方法:
$ awk 'NR==FNR{if (/apple/) hit=NR; next} {print} FNR==hit{exit}' file file
honor
apple
redmi
nokia
apple
如果這執行得不夠快,那么是時候嘗試一些替代方案,看看是否有任何方法可以提高性能。
反轉文件,從模式的第一次出現開始打印所有內容,然后反轉結果:
tac file.txt | sed -n '/apple/,$p' | tac > newfile.txt
您可以找到最后一個匹配項的行號,然后使用它來打印文件的前 N 行:
line=$(awk '/apple/ { line=NR } END {print line}')
head -n $line file.txt > newfile.txt
如果您不想像 Barmar 建議的那樣反轉文件,則必須使用較低級別的工具(例如 fseek)反轉讀取文件或讀取它兩次:
sed $(awk '/apple/{a=NR}END{print a+1}' input),\$d input
(請注意,如果該模式未出現在文件中,則不會輸出任何內容。這是您應該擔心的邊緣情況。)
這可能對你有用(GNU sed):
sed '/apple/,$!b;//!H;//{x;//p;x;h};${x;P};d' file
像往常一樣打印不是從apple
的第一次出現到文件末尾的任何行。 對於上述范圍內的行,將不包含單詞apple
行附加到保持空間 (HS)。 包含單詞apple
,首先交換到 HS 並在那里打印任何單詞apple
的行,然后將 HS 替換為包含apple
的行。 刪除除最后一行之外的所有行。 在文件末尾打印 HS 的第一行並刪除其余行。
如果吞咽大文件不是問題,請使用:
sed -rz 's/(.*apple[^\n]*).*/\1\n/' file
這使用貪婪來捕獲單詞apple
之前並包括單詞的所有行。
這是另一個沒有掃描文件兩次的awk
$ awk 'f {buf=buf ORS $0}
/apple/ {f=1; if(buf)print buf; buf=$0}
!f' file
honor
apple
redmi
nokia
apple
如果您不介意將所有內容都保存在內存中,則可以執行以下操作:
$ awk '/^apple$/{last=NR}
{lines[NR]=$0}
END{for(li=1;li<=last;li++) print lines[li]}' file
honor
apple
redmi
nokia
apple
鑒於您正在處理大量輸入,我會使用兩遍coreutils
解決方案,例如:
n=$(grep -Fn apple infile | tail -n1 | cut -d: -f1)
[ -n "$n" ] && head -n$n infile > outfile
這使用grep 的固定字符串匹配 ( -F
) 來查找包含蘋果的每一行。 然后使用head提取相關行。
您沒有指定未找到蘋果時會發生什么,因此此解決方案在發生這種情況時不執行任何操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.