我有这段代码,我确实想替换特定的模式,而不是多次就地替换。
echo "ss qq" | sed "s/ss/qq/g; s/qq/dd/g;"
结果是
dd dd
并希望是
qq dd
同样通过“循环”,我们得到相同的结果。
echo "ss qq" | sed ":loop; s/ss/qq/g; s/qq/dd/g; t loop;"
它的小巧,非常令人失望的错误!
有什么建议为什么会发生吗?
答案 0 :(得分:2)
关于“为什么发生”:sed逐行输入输入,然后依次应用每个命令。如果您查看命令的GNU sed(4.6或更高版本)的调试输出,这将变得更加清楚:
$ sed --debug 's/ss/qq/g;s/qq/dd/g' <<< 'ss qq'
SED PROGRAM:
s/ss/qq/g
s/qq/dd/g
INPUT: 'STDIN' line 1
PATTERN: ss qq # Pattern space before first command is applied
COMMAND: s/ss/qq/g
MATCHED REGEX REGISTERS
regex[0] = 0-2 'ss'
PATTERN: qq qq # Pattern space before second command is applied
COMMAND: s/qq/dd/g
MATCHED REGEX REGISTERS
regex[0] = 0-2 'qq'
PATTERN: dd dd
END-OF-CYCLE:
dd dd
答案 1 :(得分:0)
那会是
qq dd
然后按倒序进行替换:
更改sed "s/ss/qq/g;s/qq/dd/g;"
-> sed "s/qq/dd/g;s/ss/qq/g;"
答案 2 :(得分:0)
也许是您正在寻找的y///
命令的行为:
▶ echo "ss qq" | sed 'y/sq/qd/'
qq dd
这将逐个字符地将所有s
转换为q
,并将所有q
转换为d
。
答案 3 :(得分:0)
这可能对您有用(GNU sed):
sed 's/ss\|qq/\n&/;:a;s/\nss/qq\n/;s/\nqq/dd\n/;s/\n\(.\)/\1\n/;ta;s/\n//' file
这会以换行符的形式引入有关最后替换发生位置的标记。在该行的末尾,标记被删除。
使用标记的原因是因为每次替换命令的调用均从该行的开头重新开始,而不是从最后一次替换结束的地方重新开始。 g
标志可能会使问题感到困惑,但仅属于替换的当前调用。
如前所述,更好的方法是对第一个替换使用替代方法,并将其全局替换为最后一个命令。
sed 's/ss/\n/g;s/qq/dd/g;s/\n/qq/g' file