繁体   English   中英

Linux sed 正则表达式替换为捕获组

[英]Linux sed regex replace with capture groups

我有一个包含以下格式的目录条目的文件:

<item><ln></ln><fn>Some person</fn><ct>07123456789</ct><sd>37</sd><rt>1</rt><bw>1</bw></item>

我想使用sed搜索<ct>是 11 位数字和<bw>1</bw>的任何地方。 我想像这样更改上面的行:

<item><ln></ln><fn>Some person</fn><ct>07123456789</ct><sd>37</sd><rt>1</rt><bw>0</bw></item>

(如果不是很明显我已经改变了<bw> = 0)

我在sed中尝试过以下操作,但不匹配:

sed -E 's/(.+<ct>\d{11}.+<bw>)1(<\/bw><\/item>)/\10\2/g' test-directory.xml

我究竟做错了什么?

您可以将此sed与 2 个捕获组一起使用:

sed -E 's~(.*<ct>[0-9]{11}</ct>.*<bw>)1(</bw>.*)~\10\2~' file

<item><ln></ln><fn>Some person</fn><ct>07123456789</ct><sd>37</sd><rt>1</rt><bw>0</bw></item>

更多信息:

  • (.*<ct>[0-9]{11}</ct>.*<bw>) :匹配并捕获后跟<ct>11-digits</ct>后跟任何文本后跟<bw>的任何文本<bw>在捕获组 #1
  • 1
  • (</bw>.*) :匹配</bw>后跟捕获组 #2 中的任何内容

PS:这假设<ct>标签出现在同一行中的<bw>标签之前。 为了更好地控制 XML,最好使用 XML 解析器而不是 shell 实用程序。


如果<bw>标签位置不固定,那么您可以使用这个sed解决方案:

sed -E '\~<ct>[0-9]{11}</ct>~ s~(.*<bw>)1(</bw>.*)~\10\2~' file

使用awk (如果您对它没问题),您可以尝试遵循 GNU awk解决方案,该解决方案是在 GNU awk中编写和测试的,并带有显示的示例。 简单的解释是,使用awk程序的match函数,其中使用正则表达式(.*<ct>[0-9]{11}<\/ct>.*<bw>)([0-9]+)(<\/bw>.*)在其中创建 3 个捕获组(稍后使用)并根据捕获组编号存储这些值,它将在名为arr的数组中创建项目索引。 完成后,只打印需要的部分(用 0 更改任何数字,在</bw>之前)。

awk '
match($0,/(.*<ct>[0-9]{11}<\/ct>.*<bw>)([0-9]+)(<\/bw>.*)/,arr){
  print arr[1]"0"arr[3]
}
' Input_file

这是上面显示的正则表达式的在线演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM