如何合并sed命令实现匹配行及后续指定行打印,及文件末尾同类操作?
Great question! Let's tackle both parts of your problem—combining sed commands to get the start of the file plus lines after a match, and the reverse (lines before a match to the end of the file).
Printing from the start of the file to a pattern, plus N lines after
Yes, you absolutely can do this in a single sed command—no need to pipe two separate commands together. Let's use your example where we want to match dolor and include 2 lines after it.
First, let's assume your input file (example.txt) has one word per line like this:
lorem
ipsum
dolor
sit
amet
consectetur
adipiscing
elit
The goal is to print up to dolor plus the next 2 lines, resulting in:
lorem
ipsum
dolor
sit
amet
Here's a clean sed command to do this:
sed -n '1,/dolor/p; /dolor/{n;p;n;q}' example.txt
Let's break this down:
-n: Tellssedonly to print lines we explicitly specify (avoids duplicate output)1,/dolor/p: Prints every line from the start of the file up to (and including) the line matchingdolor/dolor/{n;p;n;q}: When we hit thedolorline:n: Reads the next line into the pattern spacep: Prints that linen: Reads the second line afterdolorp: Prints that lineq: Quitssedimmediately so we don't print any lines beyond this point
If you need a more flexible version (say, for any number of lines after the match, not just 2), you can use a loop with labels to count lines dynamically:
sed '/dolor/{:loop; N; s/\n/ /g; /\n.*\n/!b loop; q}' example.txt
:loop: Defines a reusable labelN: Adds the next line to the pattern space/\n.*\n/!b loop: If we don't have 2 newline characters (meaning we haven't added 2 lines after the match yet), jump back to thelooplabelq: Quit once we've collected the match plus 2 lines
Doing the reverse: Printing from N lines before a pattern to the end of the file
For the end-of-file equivalent—printing from a few lines before the match to the end of the file—we can use a similar approach, or leverage tac (which reverses the file) to reuse our earlier logic.
Using your example, if we want to print 2 lines before dolor to the end, the output would be:
ipsum
dolor
sit
amet
consectetur
adipiscing
elit
Here's how to do it with tac + sed:
tac example.txt | sed '/dolor/{:loop; N; 2ba; q}' | tac
tac example.txt: Reverses the file sodolorappears near the topsed '/dolor/{:loop; N; 2ba; q}': Grabs thedolorline plus the next 2 lines (which are the original file's lines beforedolor)tac: Reverses the result back to normal order
If you want a pure sed solution without tac, you can use the hold space to track the last N lines until you hit the match:
sed -e '1{N;N}' -e '/dolor/!{D;N;b}' example.txt
1{N;N}: Starts by reading the first 3 lines (the match line plus 2 before it)/dolor/!{D;N;b}: If the current lines don't includedolor, delete the oldest line (D), read a new line (N), and repeat the loop- Once
doloris found,sedstops looping and prints all remaining lines normally
内容的提问来源于stack exchange,提问作者jmlemetayer

