【问题标题】:How to use sed to return something from first line which matches and quit early?如何使用 sed 从第一行返回匹配并提前退出的内容?
【发布时间】:2021-02-02 07:28:00
【问题描述】:

我看到了

How to use sed to replace only the first occurrence in a file?

如何做我想做的大部分事情:

sed -n '0,/.*\(something\).*/s//\1/p'

这会找到某事物的第一个匹配项并提取它(当然我的真实示例更复杂)。我知道 sed 有一个 'quit' 命令可以使其提前停止,但我不知道如何将 'q' 与上述行结合起来以获得我想要的行为。

正如我在一些示例中看到的那样,我尝试将“p”替换为 {p;q;},但这显然不起作用。

【问题讨论】:

  • 你能更多地展示你正在得到什么、你想要什么以及它们有何不同吗?我做了echo -e "aaa 111 aaa\nbbb 111 bbb"|sed -n '0,/.*\(111\).*/s//\1/p' 并得到了一个“111”。然后我做了echo -e "aaa 111 aaa\nbbb 111 bbb"|sed -n '0,/\(.*\(111\).*\)/s//\1/p' 来显示完整的行以确保它得到了什么,它输出“aaa 111 aaa”,这是我所期望的。请注意,我没有使用q。它是如何对您“不起作用”的。
  • 您的方法会生成正确的输出,但即使没有更多工作要做,它也会继续处理整个文件,这对于大型文件或在管道中使用时很糟糕。我的具体用例是通过 git-p4 导入树上的“git log”找出最后一次提交使用了哪个 perforce 分支。 git log (当没有 -n 调用时,将记录每次发生的每一次提交(对我来说是数十万次)。我们无法先验地知道给 git '-n' 赋予什么价值。我的解决方案是:git log | sed -n '0,/.*[git-p4:.*\/\/depot\/blah\/([^\/]*)\/.*/s//\1/p; /[git- p4/q'

标签: sed


【解决方案1】:

“打印并退出”技巧有效,如果您还将替换命令放入块中(而不是仅将打印并退出那里)。

试试:

sed -n '/.*\(something\).*/{s//\1/p;q}'

像这样阅读:匹配斜线之间给出的模式。如果找到此模式,则执行块中指定的操作:替换、打印和退出。通常,匹配模式和替换模式是相等的,但这不是必需的,因此“s”命令也可以包含不同的 RE。

其实这和ghostdog74回答gawk的很相似。

【讨论】:

  • 不幸的是,在 macOS extra characters at the end of q command 上出现错误。解决方法很简单:在 q 后面加分号:{s//\1/p;q;}
【解决方案2】:

我的具体用例是通过 git-p4 导入树上的“git log”找出最后一次提交使用了哪个 perforce 分支。 git log (当没有 -n 调用时,将记录每次发生的每个提交(对我来说是数十万个))。

我们无法先验地知道 git 为“-n”赋予什么价值。发布后,我找到了我的解决方案:

git log | sed -n '0,/.*\[git-p4:.*\/\/depot\/blah\/\([^\/]*\)\/.*/s//\1/p; /\[git-p4/ q' 

我仍然想知道如何使用非“/”分隔符来执行此操作,并且不必指定“git-p4”部分两次,一次用于提取,一次用于退出。必须有一种方法可以将两者结合在同一行...

【讨论】:

    【解决方案3】:

    Sed 通常有一个选项来指定多个要执行的模式(IIRC,它是 -e 选项)。这样,您可以指定在第一行之后退出的第二个模式。

    另一种方法是使用 sed 提取第一行 (sed '1q'),然后将其通过管道传递给第二个 sed 命令(如上所示)。

    【讨论】:

      【解决方案4】:

      使用 gawk

      gawk '/MATCH/{
                  print "do something with "$0
                  exit 
      }' file
      

      【讨论】:

        【解决方案5】:

        要“从第一行返回内容并退出”,您还可以使用grep

        grep --max-count 1 'something'
        

        grep 应该比 sed 和 awk [1] 更快。即使没有,这种语法也更容易记住(并输入:grep -m1 'something')。

        如果您不想看到整行而只想看到匹配的部分,--only-matching (-o) 选项可能就足够了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-08
          • 2014-01-23
          • 1970-01-01
          • 1970-01-01
          • 2018-10-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多