如何在指定关键词后删除不含目标关键词的行及实操场景咨询
Let's break down and solve your two text manipulation problems with practical, command-line tools that are commonly used for these tasks:
Problem 1: Delete all lines after keyword1 if keyword2 doesn't exist in the file
The core idea here is to first check if keyword2 exists in the file, then stop printing lines right after keyword1 only if keyword2 is missing. We can use awk to handle this logic smoothly, as it supports state tracking and array storage for lines.
Here's the awk command you can use:
BEGIN { found_keyword2 = 0 } /keyword2/ { found_keyword2 = 1 } { lines[NR] = $0 } END { for (i=1; i<=NR; i++) { print lines[i] if (lines[i] ~ /keyword1/ && !found_keyword2) { break } } }
How it works:
- We start by initializing a flag
found_keyword2to 0 (false) in theBEGINblock. - As we read each line, if we encounter
keyword2, we setfound_keyword2to 1 (true). - We store every line in an array
linesindexed by line number (NR). - In the
ENDblock, we loop through the stored lines:- Print each line until we hit
keyword1. - If
keyword2was never found, we break the loop immediately after printingkeyword1, effectively discarding all subsequent lines. - If
keyword2exists, we'll print all lines normally.
- Print each line until we hit
To run this on your file (replace your_file.txt with your actual filename):
awk -f script.awk your_file.txt
Or as a one-liner:
awk 'BEGIN { found_keyword2 = 0 } /keyword2/ { found_keyword2 = 1 } { lines[NR] = $0 } END { for (i=1; i<=NR; i++) { print lines[i]; if (lines[i] ~ /keyword1/ && !found_keyword2) break } }' your_file.txt
Problem 2: Delete lines without test1 after the /test1/end line in test_long_sentence.txt
For this task, we need to switch into a "filter mode" once we encounter the /test1/end line: before that line, print everything; after that line, only print lines that contain test1. Again, awk provides a straightforward way to implement this with a flag.
Using awk (recommended for clarity):
/\/test1\/end/ { flag=1; print; next } flag == 1 { if (/test1/) print; next } 1
How it works:
- When we match the
/test1/endline, we set theflagto 1, print the line itself, and usenextto skip further processing for this line. - Once
flagis 1 (meaning we're after the/test1/endline), we only print the line if it containstest1; otherwise, we skip it. - The final
1is a shorthand inawkthat means "print the current line" — this applies to all lines before the/test1/endline, since the flag is still 0.
Run it directly on your file:
awk '/\/test1\/end/ { flag=1; print; next } flag == 1 { if (/test1/) print; next } 1' test_long_sentence.txt
Alternative with sed:
If you prefer sed, here's a command that achieves the same result:
'/\/test1\/end/{p;:a;n;/test1/!d;ba}' test_long_sentence.txt
How the sed command works:
- When
/test1/endis matched, we first print the line (p). - We define a label
:a, then read the next line (n). - If the line doesn't contain
test1, we delete it (d) and jump back to labelato process the next line. - If the line does contain
test1, it's printed automatically (since we don't delete it) and we jump back toato continue filtering.
内容的提问来源于stack exchange,提问作者Jojoleo




