我有一个大型 xml 文件,其中包含以下类型的行:
<test type="one" valid="yes" description="something">
twilight-.*\.iso\.auth</test>
<test type="one" valid="no" description="something else">
testlite-.*\.cop</test>
<test type="two" valid="yes" description="something else">
messing-.*\.cop\.auth</test>
<test type="three" valid="yes" description="something else">messing-.*\.cop\.auth</test>
我的 xml 文件中有很多这样的行。我的要求是:
- 如果我们匹配第一行中的模式“valid="yes"”和第二行中的“.auth”,则复制这两行。在第二行中,将“.auth”替换为“.newauth”
- 如果我们在同一行中匹配模式“valid=”yes”和“.auth”,则仅复制该行并将“.auth”替换为“.newauth”
输出应如下所示:
<test type="one" valid="yes" description="something">
twilight-.*\.iso\.auth</test>
<test type="one" valid="yes" description="something">
twilight-.*\.iso\.newauth</test>
<test type="one" valid="no" description="something else">
testlite-.*\.cop</test>
<test type="two" valid="yes" description="something else">
messing-.*\.cop\.auth</test>
<test type="two" valid="yes" description="something else">
messing-.*\.cop\.newauth</test>
<test type="three" valid="yes" description="something else">messing-.*\.cop\.auth</test>
<test type="three" valid="yes" description="something else">messing-.*\.cop\.newauth</test>
请注意,我的 xml 文件中有很多这样的行(行对)需要替换。但替换它的规则与上面相同。另请注意,对于第四行,整个 xml 标记是单行的一部分。因此,在这种情况下 awk 表达式变得稍微复杂一些。
提前致谢!
答案1
更新以满足修订后的问题
尝试这个。似乎与 GNU awk 4.2.1 一起工作正常。
awk '/valid="yes"/{print;if(!/<\/test>/){a=$0;getline;print $0"\n"a}gsub(/\.auth/,".newauth")}1' filename
答案2
使用sed
编辑器我们可以很容易地做到这一点,如下所示:
$ sed -e '
/valid="yes"/!b
h;/\.auth/G
/\n/P;//s/.*\n//
s/\.auth/.newauth/;t
$q;N;/\.auth/!{P;D;}
p;s//.newauth/
' test.xml
答案3
我能够通过两步过程实现我想要的(基于@Steve 的解决方案):
- 解决#1:
awk '/valid="yes"/{print;a=$0; next} /.auth/{print $0"\n"a;gsub(/\.auth/,".newauth")}1' test.xml > newtest.xml
- 使用上述步骤中的 xml 文件解决#2:
awk '/valid="yes"/ && /.auth/{print $0;gsub(/\.auth/,".newauth")}1' newtest.xml > final.xml
是否可以将这两个操作合并为一个 awk 操作?
答案4
如果您确实知道自己在做什么,并且您的 XML 不能采用不同的格式或包含任何陷阱,则不需要两个步骤或复杂的脚本。这个只需一次即可完成:
sed -e '/valid="yes"/!b' -e '/\.auth/!N;p;s/\.auth/.newauth/'
/valid="yes"/!b
对于不包含该模式的行 ( )跳转b
到脚本末尾!
,因此其他所有内容均保持原样/\.auth/!N
适用于不!
包含 ( ) 的行.auth
:对于这些行,我们附加N
ext 行p
打印当前模式空间(可能是一行或两行)。不管怎样,我们根据需要复制s/\.auth/.newauth/
进行所需的更换。未修改的行已被p
打印,现在我们对其进行修改以进行重复,它将在正常处理结束时打印。- 第5步?没有第5步。