【问题标题】:How to do something like grep -B to select only one line?如何执行 grep -B 之类的操作以仅选择一行?
【发布时间】:2014-08-06 22:28:04
【问题描述】:

一切都在标题中。基本上假设我有这种模式

some text lalala
another line 
much funny wow grep

我觉得很有趣,我希望我的输出是“lalala”

谢谢

【问题讨论】:

  • 只是“lalala”还是整行?您是否只想要一行带有“lalala”的行,或者任何一行恰好早于两行(即使它不包含“lalala”?
  • 是的,只是啦啦。在我的情况下,它是一个 IP 地址。我需要做的就是在我的 grep 行的末尾获取上面 8 行的 ip 地址。当您不习惯所有工具(如 cut、sed、grep 等)时,有点难。我正在努力,但很难使用这个

标签: linux bash shell scripting


【解决方案1】:

一个可能的答案是使用edex 来执行此操作(这在它们中是微不足道的):

ed - yourfile <<< 'g/funny/.-2p'

(或将ed 替换为ex。您可能也有red,这是受限制的编辑器;它不能修改文件。)这将在全局范围内查找模式/funny/,并且无论何时找到它, 在匹配行之前打印第 2 行(即 .-2p 部分)。或者,如果您想要在匹配 'funny' 的行之前包含 'lalala' 的最新行:

ed - yourfile <<< 'g/funny/?lalala?p'

唯一的问题是如果您尝试处理标准输入而不是文件;那么您必须将标准输入保存到一个文件并处理该文件,这会破坏并发性。

您不能在 sed 中进行负偏移(尽管 GNU sed 允许您进行正偏移,因此您可以使用 sed -n '/lalala/,+2p' file 将 'lalala' 变为 'funny' 行(这不是完全符合您的要求)基于查找“lalala”,但您无法根据查找“funny”找到“lalala”行)。标准 sed 根本不允许偏移。

如果您只需要打印在模式匹配行之前的第 8 行中找到的 IP 地址,则需要稍微复杂一点的 ed 脚本,但它仍然是可行的:

ed - yourfile <<< 'g/funny/.-8s/.* //p'

这使用相同的基本机制来查找正确的行,然后运行替代命令以删除行上最后一个空格的所有内容并打印修改后的版本。由于没有w 命令,它实际上并没有修改文件。

【讨论】:

    【解决方案2】:

    由于grep -B 仅在匹配前打印每个完整的行数,因此您必须将输出通过管道传输到诸如 grep 或 Awk 之类的内容中。

    grep -B 2 "funny" file|awk 'NR==1{print $NF; exit}'
    

    你也可以只使用 Awk。

    awk -v s="funny" '/[[:space:]]lalala$/{n=NR+2; o=$NF}NR==n && $0~s{print o}' file
    

    对于您评论中提到的匹配前 8 行 IP 地址的具体示例:

    awk -v s="funny" '
    /[[:space:]][0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/ {
        n=NR+8
        ip=$NF
    }
    NR==n && $0~s {
        print ip
    }' file
    

    这些 Awk 解决方案首先找到您可能想要的输出字段,然后仅当您想要的单词存在于 nth 以下行中时才打印输出。

    【讨论】:

      【解决方案3】:

      这是一个稍微概括的 Awk 解决方案的尝试。它维护最后一个q 行的循环队列,并在看到匹配时打印队列头部的行。

      #!/bin/sh
      : ${q=8}
      e=$1
      shift
      awk -v q="$q" -v e="$e" '{ m[(NR%q)+1] = $0 }
          $0 ~ e { print m[((NR+1)%q)+1] }' "${@--}"
      

      适应不同的默认值(我将其设置为 8)或正确的选项处理(目前,您会像 q=3 ./qgrep regex file 一样运行它)以及记住(并因此打印)整行应该很容易。

      (如果您在前q-1 行中看到匹配项,我也没有费心让它正常工作。然后它只会打印一个空行。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        • 2018-07-01
        • 1970-01-01
        • 2018-02-22
        • 1970-01-01
        相关资源
        最近更新 更多