【问题标题】:Print line after the match in grep [duplicate]在grep匹配后打印行[重复]
【发布时间】:2017-04-02 06:24:07
【问题描述】:

我正在尝试从“cmus-remote -Q”获取当前曲目 它总是在这条线的下方

 tag genre Various
 <some track>

现在,我需要保持简单,因为我想将它添加到我的 i3 栏。我用过

cmus-remote -Q | grep -A 1 "tag genre" 

但那个 grep 是“标记”行和下面的行。

我只想要下面的那条线。

【问题讨论】:

  • 用另一个管道排除 RE 怎么样? cmus-remote -Q | grep -A 1 "tag genre" | grep -v "tag genre" ?当然,如果 RE 连续两行,它就会失败。
  • 如果您的grep 支持-P 选项,那么它就是这么简单,grep -oPz 'tag genre.*\n\K.*' file

标签: bash grep


【解决方案1】:

您可以使用awk 代替grep

awk 'p{print; p=0} /tag genre/{p=1}' file

<some track>
  • /tag genre/{p=1} - 在一行中遇到 tag genre 时设置一个标志 p=1
  • p{print; p=0}p 不为零时,它会打印一行并将p 重置为0

【讨论】:

  • 谢谢,这也可以,但我认为 grep -v 更简单:
  • 嗯,但这会调用 2 个命令而不是 awk 的一个命令
  • 好的,很公平:)。谢谢
  • 此解决方案还假设您只想对每个文件执行一次此搜索。我认为这不是问题的标准。
  • 我们可以将exit 替换为p=0 以获得多个匹配项。
【解决方案2】:

我建议使用 awk:

awk 'seen && seen--; /tag genre/ { seen = 1 }'
  • seen 为真时,打印该行。
  • seen 为真时,减小该值,这样在打印所需的行数后将不再为真
  • 当模式匹配时,将seen设置为要打印的行数

【讨论】:

    【解决方案3】:

    如果您想使用grep 作为工具,您可以通过在管道中添加另一个段来实现:

    cmus-remote -Q | grep -A 1 "tag genre" | grep -v "tag genre"
    

    如果您要搜索的字符串连续两行,这将失败。如果我们要为它编写一些合理的东西,你必须定义在这种情况下你想要什么行为。

    另一种可能性是使用像awk 这样的工具,它可以让选线更加复杂:

    cmus-remote -Q | awk '/tag genre/ { getline; print }'
    

    这会搜索字符串,然后获取下一行,然后打印它。

    另一种可能性是单独在 bash 中执行此操作:

    while read line; do
      [[ $line =~ tag\ genre ]] && read line && echo "$line"
    done < <(cmus-remote -Q)
    

    这实现了与 awk 脚本相同的功能,只是完全不使用外部工具。它可能比 awk 脚本慢。

    【讨论】:

      【解决方案4】:

      sed:

      sed -n '/tag genre/{n;p}'
      

      输出:

      $ cmus-remote -Q | sed -n '/tag genre/{n;p}'
      <some track>
      

      【讨论】:

        猜你喜欢
        • 2012-09-22
        • 2013-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-29
        • 1970-01-01
        • 2013-11-19
        相关资源
        最近更新 更多