sed - 在第n次出现字符串之前打印所有行

时间:2014-08-01 04:30:14

标签: bash sed

假设我有:

content line 1
content line 2
blabla *my_pattern_str* (1st occurrence)
...
content line x 
blabla *my_pattern_str* (nth occurrence <- I want to print from the beginning line up to here)
content line y
content line y+1
...

我想在 my_pattern_str 的第n次出现之前打印所有行。如何使用sed(或grepawk等类似命令)执行此操作?

4 个答案:

答案 0 :(得分:3)

你可以用它。变量N是最大次数。它将处理文件的其余部分,但我不认为这是一个大问题:

awk -vN=2 'n<N;/my_pattern/{++n}' file

每次匹配模式时递增计数器。只要计数器低于变量N,就打印该行。

答案 1 :(得分:2)

根据需要调整7my_pattern

awk -v N=7 '{print}/my_pattern/&&--N<=0{exit}'

更隐晦地,以下内容也有效:

awk -v N=7 '1;/my_pattern/&&--N<=0{exit}'

上述两个实际上都停留在包含模式的第N行,而不是模式的第N次出现。如果您想要第N次出现模式:

awk -v N=7 -v M=my_pattern '1;(N-=gsub(M,""))<=0{exit}'

例如:

printf %s\\n line1 "pattern in line 2" "pattern pattern in line 3" line4 pattern |
awk -v N=3 -v M=pattern '1;(N-=gsub(M,""))<=0{exit}'

=&GT;

line1
pattern in line 2
pattern pattern in line 3

答案 2 :(得分:1)

这太可怕了,但它完全符合你的要求。

cat input_file.txt \
  | tr '\n' '\0' \
  | sed -e 's:my_pattern:my_pattern\
:g' \
  | head -n$X \
  | tr -d '\n' \
  | tr '\0' '\n'

请注意在sed模式中使用转义的换行符很棒 - 我不确定是否可以避免这种情况。

这里的想法是:

  1. \0
  2. 替换所有换行符
  3. 在每次模式匹配后插入换行符
  4. 使用head -n X抓取第一个X个匹配
  5. 删除匹配后插入的换行符
  6. 用换行符替换\0个字符
  7. (可选)在淋浴时哭。

答案 3 :(得分:0)

如果图案确实存在,那么只打印那些线条,如果找不到,则不打印所有内容:

awk '{lines[NR]=$0}/pattern/{for(i=1;i<=NR;++i)print lines[i];exit}' file