bash - 替换同一行上模式范围之间的文本

标签 bash awk sed

对于 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/

相关文章:

linux - 用于在列表中查找文件的 Bash 脚本,将它们复制到 dest,打印未找到的文件

linux - bash : Configuring email-provider for bash-script

python - 将 csv 转换为字典

linux - 如何用sed注释掉第一次出现

linux - 使用 SED 添加文本

linux - 需要替换unix文件中的一个字符

linux - 如何将命令的一部分作为变量 bash 传递?

bash - bash远程ssh更新追加替换

regex - 在同一行捕获多个正则表达式模式

linux - 在 do 循环中将参数传递给 awk