【问题标题】:extract text from xml elements using awk使用 awk 从 xml 元素中提取文本
【发布时间】:2020-12-15 01:31:49
【问题描述】:

我有一个包含大约 10k 此类 xml 标记的文件:

<!-- http://purl.obolibrary.org/obo/HP_0100516 -->

<owl:Class rdf:about="http://purl.obolibrary.org/obo/HP_0100516">
    <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The presence of a neoplasm of the ureter.</obo:IAO_0000115>
    <oboInOwl:created_by rdf:datatype="http://www.w3.org/2001/XMLSchema#string">doelkens</oboInOwl:created_by>
    <oboInOwl:creation_date rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-12-20T10:35:11Z</oboInOwl:creation_date>
    <oboInOwl:hasDbXref rdf:datatype="http://www.w3.org/2001/XMLSchema#string">UMLS:C0041955</oboInOwl:hasDbXref>
    <oboInOwl:hasRelatedSynonym rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Neoplasia of the ureters</oboInOwl:hasRelatedSynonym>
    <oboInOwl:hasRelatedSynonym>ureter, cancer of</oboInOwl:hasRelatedSynonym>
    <oboInOwl:id rdf:datatype="http://www.w3.org/2001/XMLSchema#string">HP:0100516</oboInOwl:id>
    <rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Neoplasm of the ureter</rdfs:label>
</owl:Class>
<owl:Axiom>
    <owl:annotatedSource rdf:resource="http://purl.obolibrary.org/obo/HP_0100516"/>
    <owl:annotatedProperty rdf:resource="http://purl.obolibrary.org/obo/IAO_0000115"/>
    <owl:annotatedTarget rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The presence of a neoplasm of the ureter.</owl:annotatedTarget>
    <oboInOwl:hasDbXref rdf:datatype="http://www.w3.org/2001/XMLSchema#string">HPO:probinson</oboInOwl:hasDbXref>
</owl:Axiom>

我想转换为只有 2 个 xml 元素的制表符分隔的文本文件:

Neoplasm of the ureter  The presence of a neoplasm of the ureter

通过使用 awk

我需要提取的文本在这些标签内:

<obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The presence of a neoplasm of the ureter.</obo:IAO_0000115>

<rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Neoplasm of the ureter</rdfs:label>

以及我打算使用的 awk 脚本:

BEGIN{RS="//"}
{
  match($0, regex1 , a)
  match($0, regex2, b)
  print a[1], "\t", b[1]
}

使用正则表达式获取 xml 元素内的文本的最佳方法是什么?

注意:这种方法非常有用,并证明 awk 可用于从复杂的 xml/rdf 结构中提取 xml 文本

感谢@RavinderSingh13 使用的最终 awk 脚本:

awk '
/obo:IAO_0000115 rdf:datatype/ && match($0,/>.*</,a){
  gsub(/^>|<$/,"",a[0])
  
}
/rdfs:label rdf:datatype/ && match($0,/>.*</,b){
  gsub(/^>|<$/,"",b[0])
  print b[0]"\t"a[0]
}
'  file.xml > output.txt

【问题讨论】:

  • 最好的方法是使用 XSLT 或 XML 感知工具,而不是尝试用正则表达式破解某些东西。
  • 如果您只想获取标签obo:IAO_0000115rdfs:label 的值,能否告诉我?顺便说一句,专家建议使用 xmlatrlet xml 相关工具,但如果您无法安装它们,那么我们可以继续使用awk 解决方案,请确认一次。
  • @RavinderSingh13 是的,更喜欢使用所示标签的 awk 解决方案

标签: regex xml awk


【解决方案1】:

您能否尝试以下操作,仅基于您显示的示例。此外,awk 也不是 xml 解析的理想工具,因为 OP 特别提到 OP 不能使用任何其他工具,所以在这里使用这种方法。

awk '
(/obo:IAO_0000115 rdf:datatype/ || /rdfs:label rdf:datatype/) && match($0,/>.*</){
  print substr($0,RSTART+1,RLENGTH-2)
}
'  Input_file

说明:为上述添加详细说明。

awk '                                         ####Starting awk program from here.
(/obo:IAO_0000115 rdf:datatype/ || /rdfs:label rdf:datatype/) && match($0,/>.*</){    ####Chcecking condition if line contains obo:IAO_0000115 rdf:datatype OR rdfs:label rdf:datatype AND matches everythig from > to till < in current line.
  print substr($0,RSTART+1,RLENGTH-2)         ####Printing sub-string from RSTART to till RLENGTH here, where RSTART and RLENGTH variables are set whenever a match function has TRUE/matched regex in it.
}
'  Input_file                                 ####Mentioning Input_file here.

来自man awk

RSTART match()匹配的第一个字符的索引; 0 如果 没有匹配。 (这意味着字符索引从 1 开始。) RLENGTH match()匹配的字符串长度; -1 如果不匹配。



编辑: 如果有人想从 2 个不同的字符串搜索中创建 2 个不同的数组,请按照 OP 的评论再添加 1 个解决方案,然后尝试以下操作。用 GNU awk 编写和测试。

awk '
/obo:IAO_0000115 rdf:datatype/ && match($0,/>.*</,a){
  gsub(/^>|<$/,"",a[0])
  print a[0]
}
/rdfs:label rdf:datatype/ && match($0,/>.*</,b){
  gsub(/^>|<$/,"",b[0])
  print b[0]
}
'  Input_file

【讨论】:

    猜你喜欢
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 2012-09-13
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    相关资源
    最近更新 更多