如果该值是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
如果第一个模式匹配,那么它应该跳过第二个模式。这相当于next
in awk
。
答案1
sed -e 's/online=YES/online=NO/' -e t -e 's/online=NO/online=YES/'
如果自最近读取输入行以来先前的命令已进行替换,则t
in 中的命令将分支到给定标签(如果未给出标签,sed
则分支到脚本末尾)。sed
s
在这种情况下,如果进行了第一次替换,它将绕过第二次替换。
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
因为它会检查YES
(YES1
由 匹配\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//'