【问题标题】:sed substitution dropping chunks of text [duplicate]sed替换删除文本块[重复]
【发布时间】:2020-01-19 19:52:16
【问题描述】:

我想使用 SED 在多个文件中查找和替换一小段文本。

具体我要执行的替换是:

sed -e '/35=R/s/|131=.*|/|131=$UNIQUE|/g' $f

在 $f 是文件名的 bash 脚本中运行。

sed 搜索包含字符串 35=R 的行,然后有一个非常简单的表达式来替换 |131=.*||131=) 之后的任何内容都使用 |131=$UNIQUE|

这似乎在某些文件上完美运行,但在其他情况下:

例如工作示例:

之前:

8=FIX.4.2|9=151|35=R|56=ABC|142=7848|50=STUFF|49=OTHERSTUFF|52=20250905-06:00:10.910|34=107|146=1|55=DE123|22=4|48=DE123|38=1|54=1|207=F|131=12ABC|10=243

之后:

8=FIX.4.2|9=151|35=R|56=COBA|142=7848|50=STUFF|49=OTHERSTUFF|52=20250905-06:00:10.910|34=107|146=1|55=DE123|22=4|48=DE123|38=1|54=1|207=F|131=$UNIQUE|10=243

但在其他情况下,它似乎会输出大量文本缺失。

示例不起作用:

之前:

8=FIX.4.2|9=147|35=R|34=15301|49=STUFF|52=20190905-15:27:54.305|56=OTHERSTUFF|115=STUFFY|131=1234abc|146=1|55=AB123|15=ZYX|22=4|38=1|48=AB123|54=2|207=STUFF|10=253

之后:

8=FIX.4.2|9=147|35=R|34=15301|49=STUFF|52=20190905-15:27:54.305|56=OTHERSTUFF|115=STUFFY|131=$UNIQUE|10=253

正如您所见,它在 131=$UNIQUE 之后丢失了管道后面的所有内容。我对表达式和 sed 相当陌生,所以我可能误解了替换部分。任何指针将不胜感激。

谢谢。

【问题讨论】:

    标签: regex sed non-greedy


    【解决方案1】:

    您的第一个示例(不)很幸运,因为在带有131= 的除法之后没有任何| 字符。

    这里的问题是.* 匹配任何字符序列,包括任何竖线 (|) 字符。因此,您需要从匹配的内容中排除 |。所以,不要使用.*,而是使用[^|]*

    另外,| 可能有特殊含义,因此当它不在括号中时,您可能需要转义它 (\|)。

    但即便如此,你也没有走出困境。 131= 部门显然可以在线上移动。意思是,它可能是第一个,也可能是最后一个。你可以通过消除关闭|来适应它:

    sed -e '/35=R/s/|131=[^|]*/|131=$UNIQUE/g' $f
    

    (我使用 Visual Studio 搜索和替换对此进行了测试,因为它很方便,而 sed 不是。但它可以满足您的需求。)

    要考虑131= 可能是第一个的情况,您需要添加另一个表达式:

    sed -e '/35=R/s/|131=[^|]*/|131=$UNIQUE/g' -e '/35=R/s/^131=[^|]*/131=$UNIQUE/g' $f
    

    【讨论】:

    • Sed 正则表达式是基本 RE,除非您使用 -E(或 -r,已弃用)调用 sed。就像 grep 一样。所以反斜杠| 会让它变得特别。 (这可能与 VS 搜索和替换不同。)
    • @rici 这就是适合你的 Visual Studio。
    • 我认为这更像是 sed 的一个怪癖; | 意思是现在替代品非常标准。但是像 sed 和 grep 这样的旧实用程序使用 BRE,如果你想替换,你必须在其中写 \|| 只是一个普通字符。所以你的答案在这一点上是不正确的。
    • @rici 如果可以的话,我会添加一些狡猾的词,以涵盖所有可能性。
    • 由你决定,但黄鼠狼还是错了 :-) tio.run/##LY1LC4JQEIX/…
    【解决方案2】:

    .* 表达式是“贪婪的”。这意味着它将尝试捕获尽可能多的字符。在示例中,它转到最右边的 | 符号。你应该使用这个表达式:

    sed -e '/35=R/s/|131=[^|]*|/|131=$UNIQUE|/g' $f
    

    【讨论】:

    • 我不相信 Gnu sed 的 ERE 支持包括非贪婪重复。
    • 哦,你是对的!我还是很抱歉……我已经改变了我的答案!非常感谢!我向所有人道歉。
    【解决方案3】:

    .* 替换为[^|]* 以在第一个| 之前停止.*

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-14
      • 2011-10-20
      • 1970-01-01
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 2013-11-01
      • 2015-05-08
      相关资源
      最近更新 更多