Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 替换同一行上图案范围之间的文字_Bash_Awk_Sed - Fatal编程技术网

Bash 替换同一行上图案范围之间的文字

Bash 替换同一行上图案范围之间的文字,bash,awk,sed,Bash,Awk,Sed,对于awk来说,这可能比sed更好,但目标是解析单个长字符串(它恰好是一个XML文档),并用另一个字符替换模式范围内的文本 我想保留被替换的字符数,并简单地将它们屏蔽为星号。我在python脚本中放了一些东西来解析XML树,但我感觉本地程序会快得多 假设字符串:“123123” …我想要输出:“***123” 我第一次尝试在不使用范围的情况下使用sed,得到了以下结果: $ echo "<mask>123</mask><keep>123</keep>

对于
awk
来说,这可能比
sed
更好,但目标是解析单个长字符串(它恰好是一个XML文档),并用另一个字符替换模式范围内的文本

我想保留被替换的字符数,并简单地将它们屏蔽为星号。我在python脚本中放了一些东西来解析XML树,但我感觉本地程序会快得多

假设字符串:
“123123”

…我想要输出:
“***123”

我第一次尝试在不使用范围的情况下使用
sed
,得到了以下结果:

$ echo "<mask>123</mask><keep>123</keep>" | sed "s/[0-9]/*/g"
<mask>***</mask><keep>***</keep>
编辑:事实上,即使输入中有换行符,我也不能正确理解模式范围行为(或者我的示例构造得很糟糕)

$echo“123\n123”| sed/,//s/[0-9]/*/g”
***
***

任何提示都将不胜感激。

您获得此输出的原因完全正确。这是sed的两个正则表达式的范围地址的技巧

您给sed的是
/regex1/,/regex2/
,sed将首先尝试查找与
地址1
匹配的行,即
/regex1/
,第一行匹配,很好。那么您的
地址2
也是一个正则表达式,因此:

如果addr2是一个regexp,则不会对该行进行测试 那个地址匹配

这句话来自sed的手册页

也就是说,sed从第2行开始检查您的
/regex2/
。当然,没有一行与
/
匹配,所以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>
kent$f类
234
123
123
123
234
123
123
234
肯特$sed/,//s/[0-9]/*/g“f
***
***
***
***
***
123
123
234

最后,建议不要使用正则表达式(sed/awk/grep…)处理xml。当然,您可以只使用“xml”作为示例。

不要使用范围表达式,因为它们会使简单的任务稍微简单一些,但需要完全重写或复制条件。当您的需求变得稍微有趣时,如果需要范围,请始终使用标志变量。当然,这意味着你不能用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

sed
python
一样是一个本机程序。为什么您认为其中一个会更快?
echo“123\n123”
实际上不会在Bash中生成带换行符的字符串<代码>echo$'123\n123'非常有用。谢谢你的解释。太好了!这正是我想要的。非常感谢!
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>
$ 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