到目前为止,我已经尝试过以下命令来查找和替换第一个“名称”出现的位置:
<username><![CDATA[name]]></username>
<password><![CDATA[password]]></password>
<dbname><![CDATA[name]]></dbname>
,但是它不起作用,所以我认为其中某些字符可能需要转义,等等。以便能够使用正则表达式仅匹配两个“用户名”的出现并仅替换“名称”。像这样,但是用
sed
:sed -i "s/<username><![CDATA[name]]><\/username>/something/g" file.xml
,并用“ something”替换括号中的内容。
可以吗?
/>
#1 楼
sed -i -E "s/(<username>.+)name(.+<\/username>)/something/" file.xml
我想这就是您要寻找的。
解释:
第一部分中的括号定义第二部分中可以重用的组(实际上是字符串)
第二部分中的
,
等是对第一部分中捕获的第i个组的引用(编号以1)-E
启用扩展的正则表达式(+
和分组所需)。评论
+1 -E选项
– slackmart
13年6月7日在22:03
它会留下一个备份文件,其名称(原始名称)+“-E”。
–显示名称
2015年11月13日下午5:32
在OSX上,我得到'sed:1:“ s /(<用户名>。+)name(。+ ...”:RE中未定义\ 1。我将这个问题的确切示例粘贴到文件中。我在这个文件上从这个答案中运行了命令,也许OSX具有不同的语法?
– deweydb
17年1月21日在5:52
sed的gnu版本支持“ -E”参数,但不是官方参数。联机帮助页中甚至没有提及。如果要使用扩展的正则表达式,则必须使用“ -r”参数。
–艾肯·克鲁格(Ikem Krueger)
17年9月19日在17:39
@deweydb根据此答案,您应该使用\(和\)而不是(和)。
– Zhang Buzz
17年11月12日13:56
#2 楼
sed -e '/username/s/CDATA\[name\]/CDATA\[something\]/' \
-e '/password/s/CDATA\[password\]/CDATA\[somethingelse\]/' \
-e '/dbname/s/CDATA\[name\]/CDATA\[somethingdifferent\]/' file.txt
/username/
之前的s
告诉sed仅适用于包含字符串“ username”的行。评论
优雅,高效且非常适合表壳。 +1
– lgeorget
13年6月7日在22:08
#3 楼
如果对sed
不是硬性要求,请改用专用工具。如果您的文件是有效的XML(不仅是那些看起来像XML的3个标记),则可以使用XMLStarlet:
xml ed -P -O -L \
-u '//username/text()' -v 'something' \
-u '//password/text()' -v 'somethingelse' \
-u '//dbname/text()' -v 'somethingdifferent' file.xml
以上内容在用正则表达式难以解决的情况下也可以使用:
可以替换标签的值而无需指定它们的当前值。
即使只是转义并且不包含在CDATA中,也可以替换它们的值。标签,如果有多个同名。
可以通过缩进来格式化已修改的XML。
上面的简要说明:
bash-4.2$ cat file.xml
<sith>
<master>
<username><![CDATA[name]]></username>
</master>
<apprentice>
<username><![CDATA[name]]></username>
<password>password</password>
<dbname foo="bar"><![CDATA[name]]></dbname>
</apprentice>
</sith>
bash-4.2$ xml ed -O -u '//apprentice/username/text()' -v 'something' -u '//password/text()' -v 'somethingelse' -u '//dbname/text()' -v 'somethingdifferent' file.xml
<sith>
<master>
<username><![CDATA[name]]></username>
</master>
<apprentice>
<username><![CDATA[something]]></username>
<password>somethingelse</password>
<dbname foo="bar"><![CDATA[somethingdifferent]]></dbname>
</apprentice>
</sith>
#4 楼
$ sed -e '1s/name/something/2' \
-e '3s/name/somethingdifferent/2' \
-e 's/password/somethingelse/2' sample.xml
您可以简单地使用地址作为“ s”前的数字来表示行号。替换第一场比赛。
#5 楼
您需要在\[.*^$/
命令的正则表达式部分中引用s
,在替换部分中引用\&/
,并加上换行符。正则表达式是一个基本的正则表达式,此外,您还需要为s
命令引用定界符。您必须改为引用该字符,但是更改定界符的目的通常是选择一个在替换文本或替换文本中都没有出现的分隔符。 > 您可以使用组来避免在替换文本中重复某些部分,并适应这些部分的变化。
#6 楼
要将“名称”单词替换为“某物”单词,请使用:sed "s/\(<username><\!\[[A-Z]*\[\)name\]/something/g" file.xml
这将替换所有出现的指定单词。
到目前为止,所有内容都已输出到标准输出,您可以使用:
sed "s/\(<username><\!\[[A-Z]*\[\)name\]/something/g" file.xml > anotherfile.xml
将更改保存到另一个文件。
#7 楼
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...
-r, --regexp-extended
use extended regular expressions in the script.
以便替换属性文件中的值
sed -i -r 's/MAIL\=(.+)/MAIL\=user@mymail.com/' etc/service.properties
评论
只需注意,几乎所有基于正则表达式的解决方案,除非进行了特别的设计,否则都会在输入格式发生更改时冒被破坏的风险。正则表达式对于处理XML,SGML或派生类(在我看来是这样)是一个糟糕的选择。已批准!考虑使用XQuery例如:w3schools.com/xquery/default.asp。这是用于检索和处理XML内容的W3C标准。