对于 awk
这可能是一个更好的任务比sed
,但目标是解析单个长字符串(恰好是 XML 文档)并将模式范围内的文本替换为另一个字符。
我想保留被替换字符的数量,并简单地将它们屏蔽为星号。我已经在 python 脚本中将一些东西放在一起来解析 XML 树,但感觉 native 程序会快得多。
假设字符串:"<mask>123</mask><keep>123</keep>"
...我想要输出:"<mask>***</mask><keep>123</keep>"
我第一次尝试 sed
不使用范围让我得到这个:
$ echo "<mask>123</mask><keep>123</keep>" | sed "s/[0-9]/*/g"
<mask>***</mask><keep>***</keep>
我了解到sed
可以在范围内操作,但我的理解是行为只能在一行之间切换,不能在处理单行的过程中切换。
对模式范围进行试验得到了以下结果(与我的理解一致),因此也没有用:
$ echo "<mask>123</mask><keep>123</keep>" | sed "/<mask>/,/<\/mask>/ s/[0-9]/*/g"
<mask>***</mask><keep>***</keep>
编辑:事实上,即使输入中有换行符,我也一定没有正确理解模式范围行为(或者我的示例构造不当)
$ echo "<mask>123</mask>\n<keep>123</keep>" | sed "/<mask>/,/<\/mask>/ s/[0-9]/*/g"
<mask>***</mask>
<keep>***</keep>
如有任何提示,我们将不胜感激。
最佳答案
切勿使用范围表达式,因为它们使简单的任务变得非常简单,但当您的要求变得稍微有趣时,则需要完全重写或复制条件,如果需要范围,请始终使用标志变量。当然,这意味着您不能将 sed 用于此类问题,因为它不支持变量。
无论如何,这是一个根本不直接使用范围的普通 GNU awk(用于多字符 RS 和 RT)解决方案:
$ cat file
Assuming the string: "<mask>123</mask><keep>123</keep>" ...I'd like the
$ awk -v RS='</mask>' -v ORS= '{print gensub(/(.*<mask>).*/,"\\1***",1) RT}' file
Assuming the string: "<mask>***</mask><keep>123</keep>" ...I'd like the
或者如果您需要 *
的数量来匹配它们要替换的字符数:
$ cat file
Assuming first string: "<mask>123</mask><keep>123</keep>" ...I'd like the
Assuming second string: "<mask>1234567</mask><keep>123</keep>" ...I'd like the
$ awk -v RS='</mask>' 'match($0,/(.*<mask>)(.*)/,a){ $0=a[1] gensub(/./,"*","g",a[2]) } {ORS=RT} 1' file
Assuming first string: "<mask>***</mask><keep>123</keep>" ...I'd like the
Assuming second string: "<mask>*******</mask><keep>123</keep>" ...I'd like the
关于bash - 替换同一行上模式范围之间的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43687483/