【问题标题】:Using wildcards with sed在 sed 中使用通配符
【发布时间】:2015-05-15 13:52:44
【问题描述】:

我有一个在普通 STDOUT 中嵌入了 xml 的日志文件,如下所示:

2015-05-06 04:07:37.386 [INFO]Process:102 - Application submitted Successfully ==== 1
<APPLICATION><FirstName>Test</FirstName><StudentSSN>123456789</StudentSSN><Address>123 Test Street</Address><ParentSSN>123456780</ParentSSN><APPLICATIONID>2</APPLICATIONID></APPLICATION>
2015-05-06 04:07:39.386 [INFO] Process:103 - Application completed Successfully ==== 1
2015-05-06 04:07:37.386 [INFO]Process:104 - Application submitted Successfully ==== 1
<APPLICATION><FirstName>Test2</FirstName><StudentSSN>323456789</StudentSSN><Address>234 Test Street</Address><ParentSSN>123456780</ParentSSN><APPLICATIONID>2</APPLICATIONID></APPLICATION>
2015-05-06 04:07:39.386 [INFO] Process:105 - Application completed Successfully ==== 1

我正在根据Parsing and manipulating log file with embedded xml 中提供给我的解决方案成功解析。根据那里的帖子,我使用带有以下命令的 .sed 文件:

s|<FirstName>[^<]*</FirstName>|<FirstName>***</FirstName>|
s|<StudentSSN>[^<]*</StudentSSN>|<StudentSSN>***</StudentSSN>|
s|<Address>[^<]*</Address>|<Address>***</Address>|
s|<ParentSSN>[^<]*</ParentSSN>|<ParentSSN>***</ParentSSN>|

我的问题是,有没有办法在上面的 foo.sed 文件中进行通配符匹配?例如,如果我想匹配所有 *SSN 标记并用 ** 替换它们,而不是为 StudentSSN 设置一行,为 ParentSSN 设置另一行,并且仍然产生如下输出:

2015-05-06 04:07:37.386 [INFO]Process:102 - Application submitted Successfully ==== 1
<APPLICATION><FirstName>***</FirstName><StudentSSN>***</StudentSSN><Address>*******</Address><ParentSSN>*********</ParentSSN>   <APPLICATIONID>2</APPLICATIONID></APPLICATION>
2015-05-06 04:07:39.386 [INFO] Process:103 - Application completed Successfully ==== 1
2015-05-06 04:07:37.386 [INFO]Process:104 - Application submitted Successfully ==== 1
<APPLICATION><FirstName>***</FirstName><StudentSSN>*********</StudentSSN><Address>*****</Address><ParentSSN>*********</ParentSSN>   <APPLICATIONID>2</APPLICATIONID></APPLICATION>
2015-05-06 04:07:39.386 [INFO] Process:105 - Application completed Successfully ==== 1

提前谢谢你

【问题讨论】:

  • 最有可能,但除非有令人信服的理由不使用多行,否则它可能会更好。使用更聪明的解决方案会让您自己也更难理解。

标签: regex sed


【解决方案1】:

choroba's helpful answerGNU sed 配合得很好,因为在 基本 正则表达式中使用 \| 进行交替(暗示缺少 -r选项)仅在此处受支持。

此外,OP 已经表达了使用 patterns 来匹配 similar 元素名称的愿望。

这是一个使用扩展正则表达式的解决方案,它应该适用于 Linux (GNU Sed) 和 BSD/OSX 平台 (BSD Sed):

sed -E 's%<([^>]*Name|[^>]*SSN|Address[^>]*)>[^<]*%<\1>***%g' file

注意:

  • 将元素名称的可变部分与[^&gt;]*而不是.*匹配是很重要的,以确保匹配仍然局限于开始标记。
  • BSD/OSX 扩展正则表达式(根据 POSIX 扩展正则表达式)不支持 正则表达式本身内部的反向引用(与参考 替换字符串中的捕获组匹配项),因此不会尝试将结束标记与一个匹配。
  • 虽然此命令适用于所述平台,但它符合 POSIX,因为 POSIX 仅要求支持 Sed 中的基本正则表达式。

上述命令是使用 基本 正则表达式的以下 GNU Sed 命令 的 e等效项 - 注意需要转义 @987654328 @、)|

sed  's%<\([^>]*Name\|[^>]*SSN\|Address[^>]*\)>[^<]*%<\1>***%g' file

请注意,正是使用交替 (\|) 使得该命令不可可移植,因为 POSIX 基本的正则表达式不支持它。 p>

【讨论】:

  • 是的,我正在使用 OSX。我在 sed 文件中使用此命令。 s%&lt;\([^&gt;]*Name\|[^&gt;]*SSN\|Address[^&gt;]*\)&gt;[^&lt;]*%&lt;\1&gt;***%g 不工作。可以请教吗?
  • @mklament01 s%&lt;([^&gt;]*Name|[^&gt;]*SSN|Address[^&gt;]*)&gt;[^&lt;]*%&lt;\1&gt;***%g 与 -E 完美配合!非常感谢
【解决方案2】:

您可以使用\| 的替代方法。因此,我将分隔符更改为%

sed -e 's%<\(FirstName\|StudentSSN\|Address\|ParentSSN\)>[^<]*</\1>%<\1>***</\1>%g'

【讨论】:

  • choroba 解决方案的一种变体:sed 's%&lt;\(FirstName\|.*SSN\|Address\)&gt;[^&lt;]*&lt;/\1&gt;%&lt;\1&gt;***&lt;/\1&gt;%g' file
  • @Cyrus 请原谅我的无知,但如果我说的是 Address1 和 Address2 以及 OwnerFirst,CoOwenerFirst。我做了这样的事情,并且在不平衡的括号周围出现错误:s|&lt;(.*First\|.*SSN\|Address.*\)&gt;[^&lt;]*&lt;/\1&gt;%&lt;\1&gt;***&lt;/\1&gt;| 这是我在 .sed 文件中针对我的日志文件运行的条目
  • 感谢@mklement0的解释
  • .sed 文件中这样的一行给我一个错误s|&lt;.*First\|.*SSN\|Address.*\&gt;[^&lt;]*&lt;/\1&gt;%&lt;\1&gt;***&lt;/\1&gt;| sed: 1: batchLogMasking.sed: RE 错误:重复操作符操作数无效
  • 这样的条目没有任何作用s%&lt;\(.*Name\|.*SSN\|Address.*\)&gt;[^&lt;]*&lt;/\1&gt;%&lt;\1&gt;***&lt;/\1&gt;%g 我使用的命令是` sed -f batchLogMasking.sed Batch.txt >> n.out` 其中,batchLogMasking.sed 包含上面的命令。请告知我哪里出错了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 2020-06-24
  • 2011-09-09
  • 2013-10-31
  • 1970-01-01
  • 2011-08-16
相关资源
最近更新 更多