sed 正则表达式替换

sed regex expression replace

我有一个 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.ThisIsIt

等字符串替换 com.FitDegree.SOMETHING

我能得到的最接近的是:

  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工具的正确方法:

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

我会使用一个 sed 字符 class,为简单起见使用反向引用:

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

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

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

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

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

并就地编辑:

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

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

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

你的 .+\" 很贪心,它尽可能将最后一个 " 作为分隔符。 要使其工作,您可以为所有内容定义一个非匹配组,引号除外:

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