【问题标题】:sed - Get only the replaced string from a multiline input & omit unmatched lines!sed - 仅从多行输入中获取替换的字符串并省略不匹配的行!
【发布时间】:2011-07-29 11:54:10
【问题描述】:

我希望 sed 省略所有不匹配的行,并且只输出被替换的字符串(单个/多个预期的行)。

换句话说:我有一堆干草,我只想把针归还,而不是所有的干草都被搜索过并且保持不变。

或者换句话说: 在多行字符串中搜索/替换正则表达式描述的字符串,并且只返回该字符串。 (通过 PHP 函数 http://www.php.net/manual/en/function.preg-replace.php 可以实现)

我目前的解决方法是先用 grep 过滤,然后只用管道将匹配的行输入 sed 进行替换:

echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla" | egrep "^Important1.*$" | sed -E "s/^Important1: *\b(.*)\b */\1/g"
# From the multiple line input I only want the "One One" (with pre/post whitespace removed, hence matching the word boundaries with "\b")
# And I want no "Bla bla" lines in the result!

但我希望有一个在 sed 中的单一解决方案。还是这超出了 sed 的预期用途,因此我应该更好地使用其他东西吗?顺便说一句,问题:multiline sed using backreferences 似乎有点相关,但我不确定!

【问题讨论】:

    标签: regex sed replace multiline


    【解决方案1】:

    为了保持你原来的表达方式:

    sed -E "s/^Important1: *\b(.*)\b */\1/g"
    

    您可以对sed 使用-n 选项,并将p 标志添加到s 命令的末尾,如下所示:

    sed -En "s/^Important1: *\b(.*)\b */\1/gp"
    

    证明:

    echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla" | sed -En "s/^Important1: *\b(.*)\b */\1/gp"
    

    s command 使用以下格式:

    sed OPTIONS... 's/regexp/replacement/flags'
    

    -n--silent 选项禁止自动打印模式空间1

    p 标志用于在进行替换时打印新的模式空间2

    【讨论】:

      【解决方案2】:

      编辑:以下内容已在 Mac 和 Linux 上进行了测试。

      你可以像这样使用 sed:

      echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla" | \
         sed -n 's/^Important1: *\([^ ]*\) */\1/p'
      
      OUTPUT:
      one
      

      说明

      sed -n 's/^Important1: *\([^ ]*\) */\1/p'
      
      -n # quiet / silent 
      
      {
        s/^Important1: *\([^\ ]*\) */\1/ # replace "Important1: one " with 1st group i.e. "one"
        p                  # print the replaced text
      }
      

      【讨论】:

      • 这个解决方案也有效!您能否解释一下如何以及为什么?谢谢!
      • @porg -1 到这个答案。 h;g; 完全是不必要的,可以删除,你会得到相同的答案(我的)!类似于X = Y + 1 - 1,只需写X=Y!事实上,为什么停在一对h;g; 上,为什么不停在sed -nE "/^Important1: /{h;g;h;g;h;g;h;g;h;g;s/^Important1: *\b(.*)\b *$/\1/;p}" 上,这也给出了相同的答案。 `
      • @anubhava: -E 必须是某种 mac 扩展,因为它不是 posix sed 的一部分。在任何一种情况下,如果您只是转义括号并使用 single 引号,而不是双引号来包围表达式,则不需要 -E(始终使用单引号)。因此,在您完全修改后的答案中,它将是sed -n 's/^Important1: *\([^ ]*\) */\1/p'。但现在我们回到克里斯蒂安的答案。
      • @SiegeX:不,-E 不是 mac 扩展。它是 GNU 扩展,但现在也是 POSIX 的一部分。 -E 代表扩展正则表达式。在 ERE 中,括号在默认情况下是特殊的,反斜杠会抑制它们的分组和捕获效果,而不是启用它们。 austingroupbugs.net/view.php?id=528
      • 哇,看起来很多工作都完全解决了我遇到的问题(我怀疑这是一个很常见的问题)。谢谢大家,多年后,你们坚持并找到了解决方案,让我如此轻松。 ☺
      【解决方案3】:

      此 sed 命令执行您的 egrep 和 sed 组合的操作:

      echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla"
      | sed -n -e "s/^Important1: *\b\(.*\)\b */\1/p"
      

      您执行替换,并且在替换之后只打印匹配的行。

      【讨论】:

      • 对不起,对我不起作用! Mac OS X 10.5.8 内置 sed 返回:sed: 1: "s/^Important1: *\b(.*)\ ...": \1 not defined in the RE 安装了 fink 的 Mac OS X 10.5.8 GNU sed 4.2.1 返回:sed: -e expression #1, char 31: invalid reference \1 on `s' command's RHS
      • 我的错误,sed 需要转义分组括号:"s/^Important1: *\b\(.*\)\b */\1/p"(在答案中更改)。
      • @porg:你应该改变你的选择并接受 this 答案。您选择的那个可能附有一个不错的解释,但正如我在该答案下的评论中指出的那样,答案完全是错误的。当您拉出不必要的h;g; 部分时,您会得到 my 答案,而 Christian 的答案比我的要好,因为我的答案中也有不必要的部分,尽管不像 h;g 那样令人震惊
      【解决方案4】:
      sed -n '/^Important1.*$/s/^Important1: *\b\(.*\)\b */\1/p'
      

      概念证明

      $ echo -e "Bla\nBla\nImportant1: One \nBla\nImportant2: Two\nBla\nBla" | sed -n '/^Important1.*$/s/^Important1: *\b\(.*\)\b */\1/p'
      One
      

      【讨论】:

      • 正如我刚刚提到的,您可以在替换之前跳过匹配,因为s 上的p 标志将 打印替换行(那些以Important1:).
      • @SiegeX:这对我来说很好用!与@Christian Semrau 版本的不同之处:1)省略了-e 参数2)省略了/^Important1.*$/3)用反斜杠转义了括号\( 你能详细说明一下,为什么它会起作用?谢谢!
      • 这个解决方案是正确的!有人可以投票吗,因为我自己的声望点很少。
      • @porg:如果这个答案解决了您的问题,请您点击投票计数旁边的复选标记接受它。
      • @porg: 1) 一些(所有较新的?)sed 版本接受省略的 -e 标志,因为它们可以推断 -e 是脚本参数之前唯一合理的选项。 2)正如我所指出的,在这种情况下不需要匹配,我不知道是否存在性能差异。 3)那是我的错误,sed 需要反斜杠。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-18
      • 1970-01-01
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多