【问题标题】:Update attribute value in xml using sed使用 sed 更新 xml 中的属性值
【发布时间】:2024-01-16 02:33:01
【问题描述】:

尝试使用 sed 修改 xml 中的属性值,但没有按预期工作。例如,我想更新 doc 元素中 data 属性的值。

<doc_details> 
   <map>
     <doc name="doc_name" data="doc_value" />
   <map>
</doc_details>

下面的 sed 命令没有替换预期值。我真的不知道出了什么问题,因为我是 bash 脚本的新手

sed -i "s/^<doc name=\"doc_name\".*/<doc name=\"doc_name\" value=\"new_value\"><\/doc>/g" inputFile

请注意,我不想使用 xmlstarlet,因为它可能没有安装在服务器中。

【问题讨论】:

  • sed 是这个工作的错误工具。请改用xmlstarlet (example)。
  • 您说“更新”,但字符串中没有value 属性。您的意思是“添加或更新(如果存在)”?
  • Don't Parse XML/HTML With Regex. 我建议使用 XML/HTML 解析器 (xmlstarlet, xmllint ...)。
  • 是的,sed 不是推荐的方式。但这是一个小用例,无法在服务器上安装另一个包(xmlstarlet)。
  • 您的搜索中有^,因此sed 期望它是行首,而实际上不是。

标签: xml bash shell sed


【解决方案1】:

开始调试类似的方法只是删除正则表达式的位,直到它匹配。这会给你一个很大的线索,你的正则表达式的哪个特定部分是问题所在,并且从那里弄清楚如何解决它可能很简单。

除非您需要双引号,否则请始终在 shell 字符串和脚本周围使用单引号,请参阅 https://mywiki.wooledge.org/Quotes。在这种情况下,您不需要脚本周围的双引号,并且使用它们会迫使您必须转义脚本中的所有双引号。使用/ 作为正则表达式分隔符也会迫使您转义脚本中的所有/s - 使用不同的字符,例如:#。此外,在您掌握基础知识之前,请务必将您编写的每个脚本复制/粘贴到 http://shellcheck.net 并修复它告诉您的问题。

至于您的主要问题,正如其他人所提到的,如果您不想锚定正则表达式,请不要锚定它。试试这个:

$ sed -E 's:(<doc name="doc_name").*(/>):\1 value="new_value"\2:' file
<doc_details>
   <map>
     <doc name="doc_name" value="new_value"/>
   <map>
</doc_details>

需要一个具有 -E 的 sed 来启用 ERE,但由于您已经在使用 GNU sed 来支持 -i,所以它可以正常工作。使用任何 sed 您可以:

$ sed 's:\(<doc name="doc_name"\).*\(/>\):\1 value="new_value"\2:' file
<doc_details>
   <map>
     <doc name="doc_name" value="new_value"/>
   <map>
</doc_details>

【讨论】: