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