对于awk
而言,这可能比sed
更好,但目标是解析单个长字符串(恰好是XML文档)并替换模式范围内的文本另一个角色。
我想保留被替换的字符数,并简单地将它们掩盖为星号。我在python脚本中放了一些东西来解析XML树,但感觉本机程序会更快。
假设字符串:"<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>
任何提示都将不胜感激。
答案 0 :(得分:2)
永远不要使用范围表达式,因为它们使简单任务变得非常简单,但是当您的需求变得稍微有点时需要完全重写或重复条件,如果需要范围,请始终使用标志变量。当然,这意味着您不能将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
答案 1 :(得分:1)
为什么你得到这个输出是完全正确的。这是两个正则表达式的sed范围地址的技巧。
你给sed的内容是/regex1/, /regex2/
,sed将首先尝试找到与address1
匹配的行,/regex1/
,第一行匹配,很好。那么你的address2
也是正则表达式,所以:
如果addr2是正则表达式,则不会对该行进行测试 addr1匹配。
这句话来自sed的手册页。
也就是说,sed开始从第2行检查你的/regex2/
。当然,没有一行与/<\/mask>/
匹配,所以sed只是对整个文件进行了替换。
检查此示例:
kent$ cat f
<mask>234</mask>
123
123
123
<mask>234</mask>
123
123
<keep>234</keep>
kent$ sed "/<mask>/,/<\/mask>/ s/[0-9]/*/g" f
<mask>***</mask>
***
***
***
<mask>***</mask>
123
123
<keep>234</keep>
最后只是一个建议,不要用正则表达式处理xml(sed / awk / grep ...)。当然,您可以只使用“xml”作为示例。