使用 SED 或 AWK 复制与 xml 文件中两种不同模式匹配的两行

使用 SED 或 AWK 复制与 xml 文件中两种不同模式匹配的两行

我有一个大型 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 文件中有很多这样的行。我的要求是:

  1. 如果我们匹配第一行中的模式“valid="yes"”和第二行中的“.auth”,则复制这两行。在第二行中,将“.auth”替换为“.newauth”
  2. 如果我们在同一行中匹配模式“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. 解决#1:
    awk '/valid="yes"/{print;a=$0; next} /.auth/{print $0"\n"a;gsub(/\.auth/,".newauth")}1' test.xml > newtest.xml
  1. 使用上述步骤中的 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:对于这些行,我们附加Next 行
  • p打印当前模式空间(可能是一行或两行)。不管怎样,我们根据需要复制
  • s/\.auth/.newauth/进行所需的更换。未修改的行已被p打印,现在我们对其进行修改以进行重复,它将在正常处理结束时打印。
  • 第5步?没有第5步。

相关内容