选择两个模式之间的第一个匹配。如果使用sed / awk / grep找到第三个模式,则重新开始搜索

时间:2016-03-11 09:11:47

标签: regex linux awk sed

我正在努力完成以下任务(我一直在寻找答案)。

搜索START_PATTERN和END_PATTERN1之间的文本

拥有如下结构的文件:

text
text
...
START_PATTERN
line1
line2
END_PATTERN2
text
text
...
START_PATTERN
line1
line2
END_PATTERN1
text
text
...

如果找到END_PATTERN2,任务将是重新开始搜索。因此命令输出应为:

START_PATTERN
line1
line2
END_PATTERN1

感谢您的时间!

3 个答案:

答案 0 :(得分:2)

此行适用于您的示例:

 tac file|sed '/END_PATTERN1/,/START_PAT/!d'|tac

测试:(我将xx添加到预期的块行中):

kent$  cat f
text
text
...
START_PATTERN
line1
line2
END_PATTERN2
text
text
...
START_PATTERN
xxline1
xxline2
END_PATTERN1
text


kent$  tac f|sed '/END_PATTERN1/,/START_PAT/!d'|tac
START_PATTERN
xxline1
xxline2
END_PATTERN1

修改

只接受第一场比赛,仅限awk:

awk '{a[NR]=$0}
     /START_PAT/{s=NR}
     /END_PATTERN2/{s=0}
     /END_PATTERN1/{exit}
     END{for(i=s;i<=NR;i++)print a[i]}' file

答案 1 :(得分:0)

通过在找到第一个模式后保留缓冲线并在找到END_PATTERN2后重置它来解决此问题:

awk 'x { next }
/START_PATTERN/ { n = 1; f = 1 } 
f { lines[n++] = $0 } 
/END_PATTERN1/ { f = 0; x = 1 } 
/END_PATTERN2/ { n = 1; f = 0 } 
END { for (i = 1; i < n; ++i) print lines[i] }' file

f是一个标志,用于确定是否将当前行保存到缓冲区linesn是用于索引缓冲区的计数器。处理完文件后,将打印缓冲区中的第一行n行。

我还添加了一个变量x,一旦设置,就会跳过所有行。这意味着只保存第一个匹配的块。

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed -n '/START_PATTERN/!d;:a;N;/END_PATTERN2/d;/END_PATTERN1/!ba;p;d' file

使用-n类似grep的开关。开始收集查找START_PATTERN的行。如果找到END_PATTERN2,请删除该集合。找到END_PATTERN1打印线条。