复杂字符串替换 - 多个文件,多个不同的字符串,必须包含某些文本

复杂字符串替换 - 多个文件,多个不同的字符串,必须包含某些文本

我有许多 XML 文件(Atlassian Confluence 空间导出仅供参考),我需要对其进行解析以替换某些字符串,只要该行以设置的字符串开头即可。

这是我需要解析和更改的行的示例:

<ac:structured-macro ac:name="jira" ac:schema-version="1" ac:macro-id="4dacac64-1234-8dd4-badd-acdfddf208d4"><ac:parameter ac:name="server">Jira Server Name</ac:parameter><ac:parameter ac:name="columns">key,summary,assignee,reporter,status</ac:parameter><ac:parameter ac:name="maximumIssues">20</ac:parameter><ac:parameter ac:name="jqlQuery">project = SOMECODE and issuetype = IssueType and &quot;SomeOtherThing&quot; != ExtraThing </ac:parameter><ac:parameter ac:name="serverId">6adef236-9999-66a6-72bc-e87a4cc03c47</ac:parameter></ac:structured-macro>

我需要替换的两件事是:

  • <ac:parameter ac:name="serverId">
  • <ac:parameter ac:name="server">

所有需要替换值的行都以以下内容开头:

<ac:structured-macro ac:name="jira"

“serverId”和“server”有多个不同的值,需要匹配和替换。

我尝试sed与正则表达式一起使用,但无法弄清楚如何添加正则表达式,例如: (.*?),以获取“serverId”和“server”的所有不同值。

这两行 sed 是我得到的最接近的,但我再次需要能够“模糊匹配”服务器值(即“Jira 服务器名称”)和服务器 ID 值(即 6adef236- 9999-66a6-72bc-e87a4cc03c47)

  • sed -i -e '/<ac:structured-macro ac:name="jira"/s~\(<ac:parameter ac:name="server">\)Jira Server Name\(</ac:parameter>\)~\1Replacement Server Name\2~' entities.xml

  • sed -i -e '/<ac:structured-macro ac:name="jira"/s~\(<ac:parameter ac:name="serverId">\)6adef236-9999-66a6-72bc-e87a4cc03c47\(</ac:parameter>\)~\16c3d2a6e-1234-95cb-33f3-b11a8ff01c44\2~' entities.xml

如何在 sed 命令中“通配”serverID 和服务器名称值,以便可以匹配和替换多个不同的 id/名称?

sed适合这项工作的工具吗?还有另一种/更简单的方法可以做到这一点吗?


要考虑的实际 XML 文件:

<jira>
<object class="BodyContent" package="com.atlassian.confluence.core">
<id name="id">12334762</id>
<property name="body"><![CDATA[<h1>Links</h1><p><ac:structured-macro ac:name="jira" ac:schema-version="1" ac:macro-id="a0d29f31-1212-4234-abcd-9ba23456f8cf"><ac:parameter ac:name="server">JIRA SERVER NAME</ac:parameter>6123450c-1234-acdb-8123-33333397828b</ac:parameter><ac:parameter ac:name="key">ABC-272</ac:parameter></ac:structured-macro></p><h1>Files</h1><p><ac:structured-macro ac:name="attachments" ac:schema-version="1" ac:macro-id="4f911234-1234-1234-1234-12345aad9b77" /></p>]]></property>
<property name="content" class="Page" package="com.atlassian.confluence.pages"><id name="id">443449761</id>
</property>
<property name="bodyType">2</property>
</object>
<object class="OutgoingLink" package="com.atlassian.confluence.links">
<id name="id">931112345</id>
<property name="destinationPageTitle"><![CDATA[some thing]]></property>
<property name="lowerDestinationPageTitle"><![CDATA[some thing]]></property>
<property name="destinationSpaceKey"><![CDATA[https]]></property>
<property name="lowerDestinationSpaceKey"><![CDATA[https]]></property>
<property name="sourceContent" class="Page" package="com.atlassian.confluence.pages"><id name="id">943325975</id>
</property>
<property name="creator" class="ConfluenceUserImpl" package="com.atlassian.confluence.user"><id name="key"><![CDATA[1234567890]]></id>
</property>
<property name="creationDate">2018-10-10 07:02:45.817</property>
<property name="lastModifier" class="ConfluenceUserImpl" package="com.atlassian.confluence.user"><id name="key"><![CDATA[1234567890]]></id>
</property>
<property name="lastModificationDate">2018-10-10 07:02:45.817</property>
</object>
<object class="Page" package="com.atlassian.confluence.pages">
<id name="id">123457845</id>
<property name="hibernateVersion">10</property>
<property name="title"><![CDATA[20170428 - somehing]]></property>
<property name="lowerTitle"><![CDATA[20170428 - somehing]]></property>
<collection name="bodyContents" class="java.util.Collection"><element class="BodyContent" package="com.atlassian.confluence.core"><id name="id">1234567</id>
</element>
</collection>
<collection name="contentProperties" class="java.util.Collection"><element class="ContentProperty" package="com.atlassian.confluence.content"><id name="id">1234567</id>
</element>
<element class="ContentProperty" package="com.atlassian.confluence.content"><id name="id">123456748</id>
</element>
<element class="ContentProperty" package="com.atlassian.confluence.content"><id name="id">123456749</id>
</element>
<element class="ContentProperty" package="com.atlassian.confluence.content"><id name="id">123456750</id>
</element>
<element class="ContentProperty" package="com.atlassian.confluence.content"><id name="id">123456751</id>
</element>
</collection>
<property name="version">1</property>
<property name="creator" class="ConfluenceUserImpl" package="com.atlassian.confluence.user"><id name="key"><![CDATA[1234567890]]></id>
</property>
<property name="creationDate">2018-09-20 04:52:30.727</property>
<property name="lastModifier" class="ConfluenceUserImpl" package="com.atlassian.confluence.user"><id name="key"><![CDATA[1234567890]]></id>
</property>
<property name="lastModificationDate">2018-09-20 04:57:08.072</property>
<property name="versionComment"><![CDATA[]]></property>
<property name="originalVersion" class="Page" package="com.atlassian.confluence.pages"><id name="id">878936102</id>
</property>
<property name="originalVersionId">878936102</property>
<property name="contentStatus"><![CDATA[current]]></property>
<property name="position">2143289343</property>
</object>
<object class="BodyContent" package="com.atlassian.confluence.core">
<id name="id">443449754</id>
<property name="body"><![CDATA[<h1>Links</h1><p><ac:structured-macro ac:name="jira" ac:schema-version="1" ac:macro-id="a0d29f31-acdb-1234-1234-12345ffff8cf"><ac:parameter ac:name="server">JIRA SERVER NAME</ac:parameter>6123450c-1234-acdb-8123-33333397828b</ac:parameter><ac:parameter ac:name="key">ABC-272</ac:parameter></ac:structured-macro></p><h1>Files</h1><p><ac:structured-macro ac:name="attachments" ac:schema-version="1" ac:macro-id="abcd1236-1234-1234-1234-abcd3aa12345" /></p>]]></property>
<property name="content" class="Page" package="com.atlassian.confluence.pages"><id name="id">443613611</id>
</property>
<property name="bodyType">2</property>
</object>
</jira>

答案1

如果我正确理解您的问题,只需确保使用仅适合名称或 ID 的模式即可。由于字段包含直到下一个开口的所有内容<,因此这应该很简单:

sed -i -e '/<ac:structured-macro ac:name="jira"/s~\(<ac:parameter ac:name="server">\)[^<]*\(</ac:parameter>\)~\1Replacement Server Name\2~' entities.xml

匹配[^<]*除 之外的所有字符<

请注意,这仅适用于这样的输入。理论上,xml 文件可能包含换行符或其他内容,这些内容会破坏任何不了解 xml 语法的脚本。然后最好使用像 python 脚本这样的东西import xml.etree.ElementTree

相关内容