【问题标题】:sed regex expression replacesed 正则表达式替换
【发布时间】:2018-08-22 02:05:00
【问题描述】:

我有一个包含这一行的 config.xml 文件:

<widget id="com.FitDegree.SOMETHING" version="5.1.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">

使用 bash 脚本,我需要将 com.FitDegree.SOMETHING 替换为字符串,例如 com.FitDegree.ThisIsIt

我能得到的最接近的是:

  sed -r 's/\"com\.FitDegree\..+?\"/"com.FitDegree.ThisIsIt"/' ../config.xml > tmpfile
  mv tmpfile ../config.xml

但结果是:

<widget id="com.FitDegree.ThisIsIt">

注意:它去掉了该行中的所有其他内容,例如版本、xmlns 等。

当我在正则表达式测试器上测试它时:https://regex101.com/r/nI8xB8/1 它只选择 com.FitDegree.SOMETHING

有什么办法解决这个问题吗?

【问题讨论】:

  • 这是 xmlstarlet 的工作。
  • sed 不知道如何进行非贪婪匹配。你可能想要一个像这样的字符类:'s/\"com\.FitDegree\.[^"]+\"/"com.FitDegree.ThisIsIt"/'
  • @0x5453 这就是解决方案!谢谢 - 将此作为正确答案,我会将其标记为正确

标签: regex xml bash sed xml-namespaces


【解决方案1】:

xmlstarlet工具的正确方法:

xmlstarlet ed -N ns="http://www.w3.org/ns/widgets" \
-u '//ns:widget/@id' -v 'com.FitDegree.ThisIsIt' config.xml

【讨论】:

  • 谢谢!我唯一需要改变的就是把它放在一行上,然后删除第一行末尾的 \。
【解决方案2】:

为了简单起见,我会使用 sed 字符类,并带有反向引用:

sed -e 's/\(\"com\.FitDegree\.\)[^"]*/\1ThisIsIt/' ../config.xml

如果您有可用的选项,您可以就地编辑文件:

sed -i -e 's/\(\"com\.FitDegree\.\)[^"]*/\1ThisIsIt/' ../config.xml

顺便说一句,Perl 处理正则表达式要容易得多,这将是:

perl -pe 's/("com\.FitDegree\.).*?"/\1ThisIsIt"/' ../config.xml

并就地编辑:

perl -i -pe 's/("com\.FitDegree\.).*?"/\1ThisIsIt"/' ../config.xml

【讨论】:

    【解决方案3】:

    这是一个有风险的正则表达式,但通常你知道,风险是真实的还是只是一个可以想象的风险,因为点也匹配点:

    sed 's,com.FitDegree.SOMETHING,com.FitDegree.OtherThing,' sample-2.xml
    

    您的 .+\" 是贪婪的,并且可以将最后一个 " 作为分隔符。 为了使其工作,您可以为所有内容定义一个不匹配的组,引号除外:

    sed -r 's/\"com\.FitDegree\.[^"]+?"/"com.FitDegree.ThisIsIt"/'
    #                           ^^^^  ^no masking needed 
    

    【讨论】:

      猜你喜欢
      • 2021-12-31
      • 2012-01-26
      • 1970-01-01
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-18
      相关资源
      最近更新 更多