i want to delete all the lines after the last occurence of pattern except the pattern itself
file.txt
honor
apple
redmi
nokia
apple
samsung
lg
htc
file.txt what i want
honor
apple
redmi
nokia
apple
what i have tried
sed -i '/apple/q' file.txt
this deletes all the line after the first occurence of pattern -
honor
In Bash (and ksh, zsh, dash, etc.), you can use parameter expansion with % which will remove characters from the end of the string or # which will remove characters from the beginning of the string. If you use a single one of those characters, the smallest matching string will be removed.
Simple, robust 2-pass approach using almost no memory:
$ awk 'NR==FNR{if (/apple/) hit=NR; next} {print} FNR==hit{exit}' file file
honor
apple
redmi
nokia
apple
If that doesn't execute fast enough THEN it's time to try some alternatives to see if any produce a performance improvement.
Reverse the file, print everything starting from the first occurrence of the pattern, then reverse the result:
tac file.txt | sed -n '/apple/,$p' | tac > newfile.txt
You can find the line number of the last match, then use that to print the first N lines of the file:
line=$(awk '/apple/ { line=NR } END {print line}')
head -n $line file.txt > newfile.txt
If you don't want to reverse the file as Barmar suggests, you will either have to read the file in reverse using lower level tools (eg, fseek) or read it twice:
sed $(awk '/apple/{a=NR}END{print a+1}' input),\$d input
(Note that if the pattern does not appear in the file, this will output nothing. That's an edge case you should worry about.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With