在匹配模式后提取第N行

7

我希望使用 grepawksed 提取匹配模式后的第 N 行。

例如,我有这段文本:

      Revision:
      60000<br />

我希望提取60000。

我尝试使用Revision:([a-z0-9]*)\s*([0-9]){5}来匹配版本和版本号,但是当我将其传递给grep:grep Revision:([a-z0-9]*)\s*([0-9]){5} file.html时,没有结果。

我该如何实现?

3个回答

31

要提取匹配模式后的第N行,您需要:

awk 'c&&!--c;/pattern/{c=N}' file

例如

awk 'c&&!--c;/Revision:/{c=5}' file

将会打印文本“Revision:”后的第5行。

更多信息请参见使用sed或awk打印匹配模式后的行


3
c&&!--c 可以等价于 c!=0 && --c==0,而 c&&c-- 可以等价于 c!=0 && --c>=0;这些替代方法可能更容易理解。 - musiphil
1
有一个警告,即如果在到达下一个N行之前再次出现模式,则计数器将被重置,并且早期出现的模式将被遗忘。例如,在c)中,如果N = 10且模式在第21行和第28行中,则仅打印第38行而不是第31行。为了解决这个问题,您可以使用awk '/pattern/{p[NR+N]=1} NR in p'(更简单)或awk '/pattern/{p[NR+N]=1} NR in p{print; delete p[NR]}'(保持内存使用量有限)。 - musiphil
如何修改 f.) 以使其不打印带有模式的行(它现在正在这样做)? - Betlista
如此回答 - http://stackoverflow.com/questions/38895234/combine-v-option-for-grep-with-a-option 修改为 awk '/abc/ {c=0} c++>4' file - Betlista
@Betlista 不是的,你只需要交换识别条件的部分并跳过行以获取重新排列的 awk '/pattern/{c=N} c&&c--{next} 1' file。而你所写的 awk '/abc/ {c=0} c++>4' file 则做了一些完全不同的事情,例如它会无条件地跳过输入的前5行。 - Ed Morton

6

打印第一个空白行后的lnb行:

要打印的行索引(在bash shell中):

lnb=2
  • Using sed:

    sed -ne '/^\s*$/{:a;n;0~'"$lnb"'!ba;p;q}' my_file`
    
  • Using perl:

    perl -ne '/^\s+$/ && $k++;$k!=0 && $k++ && $k=='"$lnb"'+2 && (print,last)' my_file`
    

打印正则表达式匹配后的第lnb行:

  • Using sed:

    sed -ne '/regex/{:a;n;0~'"$lnb"'!ba;p;q}' my_file
    
  • Using perl:

    perl -ne '/regex/ && $k++;$k!=0 && $k++ && $k=='"$lnb"'+2 && (print,last)' my_file
    

    Bonus 1, Windows PowerShell (install Perl first) :

    $lnb=2
    
    perl -ne "/regex/ && `$k++;`$k!=0 && `$k++ && `$k==$lnb+2 && (print,last)" my_file
    

    Bonus 2, Windows DOS command line :

    set lnb=2
    
    perl -ne "/regex/ && $k++;$k!=0 && $k++ && $k==%lnb%+2 && (print,last)" my_file
    

在正则表达式匹配后打印所有第lnb行:

  • Using perl(bash example):

    perl -ne '/regex/ && $k++;$k!=0 && $k++ && $k=='"$lnb"'+2 && (print,$k=0)' my_file
    

干得好。还可以花点时间参观一下[tour],了解一下Stack Overflow的全部内容。 - kvantour
谢谢,我会接受。 - lerems04

1

我喜欢可以学会重复使用的解决方案,而不必每次都要谷歌搜索。这个解决方案并不完美,但使用了简单的grep命令,我可以从记忆中编写。

grep -A7 "searchpattern" file | grep -B1 "^--$" | grep -v "^--$"

您可以将7更改为搜索模式后要查找的第n行。然后搜索“组分隔符”--并显示该行之前的最后一行。然后删除组分隔符。
唯一无法正确工作的情况是,如果您的数据包含仅为“--”的行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接