如何交换线上的值?

如何交换线上的值?

如果该值是YES,则执行它NO。如果是的话就NO做到吧YES。我使用以下命令作为示例:

( echo "online=YES"; echo "online=NO" ) | sed -e 's/online=YES/online=NO/' -e 's/online=NO/online=YES/'

online=YES
online=YES

如果第一个模式匹配,那么它应该跳过第二个模式。这相当于nextin awk

答案1

sed -e 's/online=YES/online=NO/' -e t -e 's/online=NO/online=YES/'

如果自最近读取输入行以来先前的命令已进行替换,则tin 中的命令将分支到给定标签(如果未给出标签,sed则分支到脚本末尾)。seds

在这种情况下,如果进行了第一次替换,它将绕过第二次替换。


online=YES对于可能有多个或online=NO一行的情况,使用

sed -e 's/online=YES/online=MAYBE/g' \
    -e 's/online=NO/online=YES/g' \
    -e 's/online=MAYBE/online=NO/g' 

其中字符串MAYBE不以其他方式与online=模式关联。这本质上类似于使用临时变量交换两个变量的值。

测试:

$ echo "online=YES online=YES online=NO online=YES" | sed -e 's/online=YES/online=MAYBE/g' -e 's/online=NO/online=YES/g' -e 's/online=MAYBE/online=NO/g'
online=NO online=NO online=YES online=NO

n该命令不能完全代替第一个示例中的命令的原因t是,这将在脚本中途读取下一行输入并运行该行上脚本的后半部分:

$ ( echo "online=YES"; echo "online=YES" ) | sed -e 's/online=YES/online=NO/' -e n -e 's/online=NO/online=YES/'
online=NO
online=YES

您将获得两行相同的输出NO

答案2

一些perl技巧:

perl -pe 's/online=\K(YES|NO)/$1 eq "YES" ? "NO" : "YES"/ge'
perl -pe 's/online=\K(YES(?{$r = "NO"})|NO(?{$r = "YES"}))/$r/g'

这个相关问题的答案概括第二个示例中的方法。

在这里,您还可以使用哈希来定义要应用于以下单词的翻译表online=

 perl -pe 'BEGIN{%s = (YES => NO, NO => YES)}
           s{online=\K\w+}{$s{$&} // $&}ge'

与以前的解决方案的区别在于,它不会更改online=YES1为,online=NO1因为它会检查YESYES1由 匹配\w+)。

答案3

使用t@Kusalananda 指出的命令适用于您的示例(以及大多数其他示例)。要在一次替换中实际交换两个字符串,您可以执行类似的操作

sed 'H;x;s/^/#NO#YES#NO/;s/.*#\(.*\)#\([^#]*\).*\n\(.*online=\)\1/\3\2/'

这可以轻松扩展到三个或更多字符串进行旋转。

要处理更多行、包含更多替换的行或根本没有替换的行,您可以将其扩展以循环替换:

sed -e 'H;x;s/online=/&#/g;s/^/#NO#YES#NO#/;:a' -e 's/\(.*#\)\(.*\)#\([^#]*\)\(#.*\n\)\(.*online=\)#\2/\1\2#\3\4\5\3/;ta' -e 's/.*\n//'

相关内容