简体   繁体   English

sed是否自动就地替换?

[英]Is sed auto in-place substitution?

I have this code, which I do want for replacement of a specific pattern, but not multi in-place replacement. 我有此代码,我想替换特定的模式,但不希望进行多次就地替换。

 echo "ss qq" | sed  "s/ss/qq/g; s/qq/dd/g;"

The result is 结果是

dd dd

and wish it would be 并希望是

qq dd

Also via "looping" we get the same result. 同样通过“循环”,我们得到相同的结果。

echo "ss qq" | sed  ":loop; s/ss/qq/g; s/qq/dd/g; t loop;"

its petty, very disappointing bug !! 它的小巧,非常令人失望的错误!

Any suggestion why it's happening? 有什么建议为什么会发生吗?

As for "why it's happening": sed takes the input line by line, then applies each command sequentially. 至于“为什么发生”:sed逐行输入输入,然后依次应用每个命令。 This becomes more clear if you look at the debug output of GNU sed (4.6 or newer) for your command: 如果查看命令的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

whish it would be 希望如此

qq dd qq dd

then you do the substitution in invert order: 然后您以相反的顺序进行替换:

change sed "s/ss/qq/g;s/qq/dd/g;" 更改sed "s/ss/qq/g;s/qq/dd/g;" -> sed "s/qq/dd/g;s/ss/qq/g;" -> sed "s/qq/dd/g;s/ss/qq/g;"

Maybe it is the behaviour of the y/// command you are looking for: 也许是您要查找的y///命令的行为:

▶ echo "ss qq" | sed 'y/sq/qd/'                 
qq dd

This will transform all s into q and all q into d character by character. 这将一个字符一个字符地将所有s转换为q ,将所有q转换为d

This might work for you (GNU sed): 这可能对您有用(GNU sed):

sed  's/ss\|qq/\n&/;:a;s/\nss/qq\n/;s/\nqq/dd\n/;s/\n\(.\)/\1\n/;ta;s/\n//' file

This introduces a marker in the form of a newline, as to where the last substitution occurred. 这将以换行符的形式引入有关最后替换发生位置的标记。 At the end of the line the marker is removed. 在该行的末尾,标记被删除。

The reason for the marker is because each invocation of a substitution command starts afresh from the beginning of the line, not from where the last substitution finished. 使用该标记的原因是因为每次替换命令的调用均从该行的开头重新开始,而不是从最后一次替换结束的地方开始。 The g flag may confuse the issue but only belongs the current invocation of the substitution. g标志可能会使问题感到困惑,但仅属于替换的当前调用。

As already mentioned, a better way is to is to use an alternative for the first substitution and replace this globally as the last command. 如前所述,更好的方法是对第一个替换使用替代方法,并将其全局替换为最后一个命令。

sed 's/ss/\n/g;s/qq/dd/g;s/\n/qq/g' file 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM