sed 多行替换

sed 多行替换

我需要将owl:Class下面的文本替换为 LP 编号

输入:

<owl:Class rdf:about="https://loinc.org/LP173100-1">
        <rdfs:subClassOf rdf:resource="https://loinc.org/LP410935-3"/>
        <rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Counseling (LP)</rdfs:label>
        <skos:prefLabel rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Counseling</skos:prefLabel>
        <loinc:hasCode rdf:datatype="http://www.w3.org/2001/XMLSchema#string">LP173100-1</loinc:hasCode>
    </owl:Class>

这样替换后的输出如下所示

输出:

<"LP173100-1" rdf:about="https://loinc.org/LP173100-1">
        <rdfs:subClassOf rdf:resource="https://loinc.org/LP410935-3"/>
        <rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Counseling (LP)</rdfs:label>
        <skos:prefLabel rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Counseling</skos:prefLabel>
        <loinc:hasCode rdf:datatype="http://www.w3.org/2001/XMLSchema#string">LP173100-1</loinc:hasCode>
    </"LP173100-1">

我已用于s/\(owl:Class\)\(.*org\/\)\(LP.*\)"/"\3"\2\3/g第一行,但我不知道如何将其应用到最后一行。有更优雅的解决方案吗?我有一个巨大的文件,我需要在其中进行此类替换。

我使用的是 CentOS 7.7 机器。

答案1

使用 GNU sed,并假设您的文件仅包含示例中的 6 行:

$ sed -e '1{h; s/\(owl:Class\)\(.*org\/\)\(LP.*\)"/"\3"\2\3"/}; 6{G; s/\(owl:Class\)\(.*org\/\)\(LP.*\)"/"\3"/}'  infile
<"LP173100-1" rdf:about="https://loinc.org/LP173100-1">
      <rdfs:subClassOf rdf:resource="https://loinc.org/LP410935-3"/>
      <rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Counseling (LP)</rdfs:label>
      <skos:prefLabel rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Counseling</skos:prefLabel>
      <loinc:hasCode rdf:datatype="http://www.w3.org/2001/XMLSchema#string">LP173100-1</loinc:hasCode>
   </"LP173100-1">
$

解释:

在正则表达式模式中,反向引用用于匹配与先前匹配的子表达式相同的内容。

模式空间是 sed 的内部缓冲区,sed 在其中放置并可能修改从输入文件读取的行。

保留空间是一个额外的内部 sed 缓冲区,sed 可以在其中保存临时数据。

  • 1{...};仅将大括号之间的命令应用于第一行
  • h;保存模式空间,即未修改的第一行,以容纳空间
  • s///在模式空间中进行实际的搜索/替换
  • \(owl:Class\)在模式空间中搜索字符串“owl:space”。匹配的子表达式可以通过反向引用 \1 来调用
  • \(.*org\/\)如前所述,匹配“ rdf:about="https://loinc.org/",反向引用为 \2
  • \(LP.*\)如前所述,匹配“LP173100-1”,反向引用为 \3
  • /"\3"\2\3"/输出双引号中的第三个子表达式字符串,即“LP173100-1”,后跟第二个子表达式字符串,后跟第三个子表达式字符串,后跟双引号。
  • 6{...};仅将大括号之间的命令应用于第六行
  • G;将保留空间附加到模式空间。注意 - 如果使用,您会丢失前导空格x
  • s///在模式空间中进行实际的搜索/替换
  • \(owl:Class\)在模式空间中搜索字符串“owl:space”。匹配的子表达式可以通过反向引用 \1 来调用
  • \(.*org\/\)如前所述,匹配“rdf:about=”https://loinc.org/”,反向引用为 \2
  • \(LP.*\)如前所述,匹配“LP173100-1”,反向引用为 \3
  • /"\3"/输出双引号之间的第三个子表达式字符串。

还有其他方法可以使用 来做到这一点吗sed?绝对地。这是最有效的方法吗sed?可能不会。

相关内容