【问题标题】:How to grep by section?如何按部分grep?
【发布时间】:2013-03-20 18:56:58
【问题描述】:

我有一个这样的文件:

BOF

-------Title1-------
stuff here
some stuff

-------Title2-------
extra things
extra things
extra things

-------Title3-------
and some stuff
   here

...

-------Title4-------
stuff

EOF

现在我想做这样的事情:

grep-by-section KEYWORD DELIMITER my-file

这样

grep-by-section "some" "^---" my-file

输出

-------Title1-------
stuff here
some stuff

-------Title3-------
and some stuff
   here

我想找到一个特定的关键字,并且对于每个发现我想输出已知分隔符之间的整个块。我怎样才能做到这一点? sed 让我失望了。

这里的分隔符是“------”,但也可以是其他东西,例如 [0-9]{8} 格式的数字。

一个我无法解决的类似问题是不输出块的内容,只输出块的标题。

使用perl 似乎比sed 更容易解决

【问题讨论】:

  • 我认为awk 会是一个很好的解决方案。类似情况见this topic。

标签: regex perl parsing sed grep


【解决方案1】:
#!/usr/bin/perl
my ($search, $del) = splice(@ARGV, 0, 2);
local $/;
while (<>) {
   for (/($del(?:(?!$del).)*)/smg) {
      print if /$search/sm;
   }
}

注意事项:

  • local $/ 导致以下 readline 一次读取一个文件,而不是一次读取一行。
  • (?:(?!STRING).)* 是 STRING 就像 [^CHAR]* 是 CHAR。

【讨论】:

  • 哇。这太棒了,但你能让我们凡人更容易阅读吗? ;)(嗨 ikegami!)
【解决方案2】:

如果这些记录之间有真正的空行,则不需要使用这些分隔符,这就足够了:

awk '/KEYWORD/' RS= ORS='\n\n' file

否则你也可以试试这个 awk:

awk '
  $0~key{
    f=1
  }
  $0~del{
    if(f)print s
    f=0
    s=$0
    next
  }
  {
    s=s RS $0
  }
  END{
    if(f)print s
  }
' key="KEYWORD" del="DELIMITER" file

一行:

awk '$0~key{f=1} $0~del{ if(f)print s ; f=0; s=$0; next } {s=s RS $0} END{ if(f)print s }' key="KEYWORD" del="DELIMITER" file

【讨论】:

    【解决方案3】:

    agrep 可以通过以下方式进行:agrep -d DELIMITER KEYWORD FILE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      相关资源
      最近更新 更多