![](/img/trans.png)
[英]Replace multiple lines on multiple files with the same pattern on Powershell
[英]How to use awk to insert multiple lines after first match of a pattern, in multiple files
我有一个包含许多子目录的目录,每个子目录包含我要编辑的config.xml
文件。 喜欢:
../jobs/foo_bar-v1.2_west/config.xml
../jobs/foo_bar-v1.3_west/config.xml
../jobs/foo_stuff-v1.3_east/config.xml
../jobs/foo_foo-v9.8_north/config.xml
../jobs/NOT_FOO-v0.1_whatev/config.xml
etc.
在匹配特定行的第一个实例<properties>
之后,我需要一种将多行文本插入到多个../jobs/foo*/config.xml
文件中的方法。
要插入的文本如下所示:
<a.bunch.of.TextGoesHere>
<permission>one.foo.Items.Foo:person.name</permission>
<permission>two.foo.Items.Foo:person.name</permission>
<permission>three.foo.Items.Foo:person.name</permission>
</a.bunch.of.TextGoesHere>
每个../jobs/foo*/config.xml
如下所示:
<?xml version='1.0' encoding='UTF-8'?>
<foo1>
<actions/>
<description>foo2</description>
<keepDependencies>false</keepDependencies>
<properties>
<foo3/>
</properties>
...
<lots_of_other_stuff>
<properties>
<junk>
</properties>
每个config.xml
最终输出应如下所示:
<?xml version='1.0' encoding='UTF-8'?>
<foo1>
<actions/>
<description>foo2</description>
<keepDependencies>false</keepDependencies>
<properties>
<a.bunch.of.TextGoesHere>
<permission>one.foo.Items.Foo:person.name</permission>
<permission>two.foo.Items.Foo:person.name</permission>
<permission>three.foo.Items.Foo:person.name</permission>
</a.bunch.of.TextGoesHere>
<foo3/>
</properties>
...
<lots_of_other_stuff>
<properties>
<junk>
</properties>
我尝试使用sed
在特定行之后插入,例如
#!/bin/bash
find ../jobs/run* -name config.xml -exec sed -i '6a\
<text to insert>' {} \;
但是偶尔, config.xml
中的长<description>
文本会导致插入时出现不可预测的行号。
接下来,我尝试使用sed
搜索<properties>
的第一个实例,然后在其后插入,例如
sed -i '0,/properties/a test' config.xml
但这导致在每一行之后添加test
测试,直到找到<properties>
。 使用sed -i '1,/
具有相似的结果。 真丑。
我不确定我是否在此Amazon Linux机器上正确使用sed
,并认为awk
在这里可能会更好。 有人可以协助吗? 谢谢。
使用GNU awk进行就地编辑时,您所需要做的就是:
awk -i inplace '
NR==FNR { text = (NR>1 ? text ORS : "") $0 }
FNR==1 { cnt=0 }
{ print }
/<properties>/ && !cnt++ { print text }
' file_containing_text_to_insert ../jobs/foo*/config.xml
假设要插入的文本在一个名为insert
的文件中:
sed -e '0,/<properties>/{/<properties>/r insert' -e '}' config.xml
r
命令读取文件并将其附加在当前行之后; 的
0,/pattern/{/pattern/r filename}
确保仅pattern
的第一个实例会附加文本。 由于命令必须在r
读取文件名之后结束,因此必须使用-e
将其分为两部分。
要就地编辑文件,请使用sed -i
(对于GNU sed)。
要对多个文件执行此操作,可以使用find
:
find jobs -name 'config.xml' \
-exec sed -i -e '0,/<properties>/{/<properties>/r insert' -e '}' {} +
这要求insert
文件位于运行此命令的目录中。
您的命令看起来几乎是正确的,除了您没有在范围内嵌套第二个地址以确保追加仅发生一次。
跟进我的评论并给出答案:
输入的xml文件“ file.xml”
<?xml version='1.0' encoding='UTF-8'?>
<foo1>
<actions/>
<description>foo2</description>
<keepDependencies>false</keepDependencies>
<properties>
<foo3/>
</properties>
...
<lots_of_other_stuff />
<properties>
<junk />
</properties>
</foo1>
xslt样式表“ file.xslt”
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Identity transform -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- insert the new stuff before the first child of the first properties element -->
<xsl:template match="/foo1/properties[1]/*[1]">
<a.bunch.of.TextGoesHere>
<permission>one.foo.Items.Foo:person.name</permission>
<permission>two.foo.Items.Foo:person.name</permission>
<permission>three.foo.Items.Foo:person.name</permission>
</a.bunch.of.TextGoesHere>
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
结果,使用xmlstarlet
$ xmlstarlet transform file.xslt file.xml
<?xml version="1.0"?>
<foo1>
<actions/>
<description>foo2</description>
<keepDependencies>false</keepDependencies>
<properties>
<a.bunch.of.TextGoesHere><permission>one.foo.Items.Foo:person.name</permission><permission>two.foo.Items.Foo:person.name</permission><permission>three.foo.Items.Foo:person.name</permission></a.bunch.of.TextGoesHere><foo3/>
</properties>
...
<lots_of_other_stuff/>
<properties>
<junk/>
</properties>
</foo1>
应用于所有文件:
find . -name config.xml -exec sh -c '
for xmlfile; do
xmlstarlet transform xform.xslt "$xmlfile" > "$xmlfile".new &&
ln "$xmlfile" "$xmlfile".bak &&
mv "$xmlfile".new "$xmlfile"
done
' sh {} +
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.