sed 自动就地替换吗?

Posted

技术标签:

【中文标题】sed 自动就地替换吗?【英文标题】:Is sed auto in-place substitution? 【发布时间】:2019-10-13 01:47:26 【问题描述】:

我有这段代码,我确实想用它来替换特定的模式,而不是多就地替换。

 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;"

它的小错误,非常令人失望!

有什么建议为什么会发生?

【问题讨论】:

sed 分号分隔的命令是连续执行的,这就是原因。请参阅可能对您有用的this thread。 试试这里发布的解决方案:***.com/a/26568996/6515775 如果只需要更改单个字母(而不是单词),您可以使用trecho "ss qq" | tr sq qd 给出qq dd 【参考方案1】:

至于“为什么会发生”: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

【讨论】:

@mr.tee 它需要 GNU sed 4.6 或更高版本,但原理相同——调试输出仅用于说明。【参考方案2】:

希望是这样的

qq dd

然后你以相反的顺序进行替换:

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

【讨论】:

【参考方案3】:

也许这是您正在寻找的y/// 命令的行为:

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

这会将所有s 转换为q 并将所有q 转换为d 逐个字符。

【讨论】:

【参考方案4】:

这可能对你有用(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 

【讨论】:

以上是关于sed 自动就地替换吗?的主要内容,如果未能解决你的问题,请参考以下文章

linux中sed命令批量修改

linux sed 替换

Shell sed 如何替换单引号,回车符,以及分号

如何就地替换数组元素

sed 查找并替换为大括号

用 sed 找到匹配时替换整行