打印文件最多为第N个匹配

时间:2013-11-06 01:59:06

标签: regex bash sed awk

我正在尝试拆分文件。 sed可用于执行此操作,例如

sed -e '0,/expr/d' filename

会在“expr”之后给出文件的下半部分但是如果有多次出现并且我想在第n次出现之后拆分怎么办?我想在第二次出现之后是否需要它

sed -e '0,/expr/! {/expr/,$d}' filename

将文件的上半部分提供到“expr”的第二个匹配项。感叹号(!)告诉它忽略第一个范围,只将大括号中的命令应用到文件的其他部分。

但更一般的情况呢?例如,从最后一次出现。

我一直在这里使用sed,但我认为awk也会有优雅的解决方案。

3 个答案:

答案 0 :(得分:2)

简单的awk解决方案:

  1. 直至并包括$n的{​​{1}}匹配:

    /regex/

  2. 最多但不包括awk -vn=$n '{print}/regex/&&!--n{exit}'匹配:

    $n

    在上述两个程序中,将n设置为0将打印整个文件。此外,awk -vn=$n '/regex/&&!--n{exit}{print}'的两种用法都可以更改为{print},因为默认操作为1;。 (或者只是第二个程序中的{print}。)

    为了完整性:

  3. 1匹配后的所有内容:

    $n

  4. 注意:正如@ mklement0的评论所指出的,在BSD Awk版本中有一个命令行选项解析的错误(又名“one-true-awk”,编写的版本,据我所知仍然由Brian Kernighan维护)2010年5月23日之前;这显然包括随Mac OS X一起发布的版本(截至v10.9)。因此,如果您使用其中一个awk版本,则需要编写awk -vn=$n 'n<=0;/regex/{--n}'而不是-v n=$n

答案 1 :(得分:2)

除了 @rici 的解决方案之外,还有awk的更多变体

  1. 直至并包括$n匹配:

    awk -v n=$n 'p<n; /regex/{p++}' file

  2. 最多但不包括$n匹配:

    awk -v n=$n '/regex/{p++} p<n' file

  3. 包括$n匹配

    awk -v n=$n '/regex/{p++} p>=n' file

  4. 来自且不包括$n匹配

    awk -v n=$n 'p>=n; /regex/{p++}' file


  5.   

    但更一般的情况呢?例如,从倒数第二个   发生。

    在这种情况下,简单的方法是使用tac读取文件反向,执行上述选项并反向再次打印。

    1. 包括$n最后一场比赛

      tac file | awk -v n=$n 'p<n; /regex/{p++}' | tac

    2. 从最后一场比赛开始,不包括$n

      tac file | awk -v n=$n '/regex/{p++} p<n' | tac

    3. 最后一场比赛<{1}}

      $n

    4. 最后一次不包括tac file | awk -v n=$n '/regex/{p++} p>=n' | tac最后一场比赛

      $n


    5. OS X用户注意,如 @ mklement0 在评论中指出

      • 糟糕的[股票] OS X用户(从OS X 10.9开始)运气不好:那里没有tac file | awk -v n=$n 'p>=n; /regex/{p++}' | tac

      • 在操作系统X上
      • 您可以使用tac(请注意,Linux上的tail -r似乎不支持tail)。

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed -nr 'x;/^X{2}/{x;p;b};x;/REGEXP/{x;s/^/X/;x}' file

这将在REGEXP的第二场比赛后打印出任何内容。

N.B。REGEXP每行可能会出现一次或多次,但只会被计算一次。