更改Bash中的标签文本

时间:2018-12-08 17:13:28

标签: xml bash sed

我有很多这样的XML格式的文本文件:

<TITLE>title</TITLE>
<TEXT>text</TEXT>

但是我需要将标签的文本更改为以下形式:

<field name="title">title</field>
<field name="text">text</field>

我正在尝试用bash写一个小脚本,并使用sed命令更改标签的文本。

sed "s/<TEXT>/<field name"text">/g"

我对每个标签使用此命令,但是这些文件包含20多个不同的标签,因此我认为必须有一种更有效的方法来执行此任务。

谢谢您的帮助。

编辑:添加了示例输入和输出。

输入

<?xml version="1.0" encoding="UTF-8"?>
<DOC>
    <DOCID>MF-20020103001</DOCID>
    <DATE>01/03/02</DATE>
    <TITLE>Example title</TITLE>
    <TEXT>Very long text...</TEXT>
</DOC>

输出

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <field name="docid">MF-20020103001</field>
    <field name="date">01/03/02</field>
    <field name="title">Example title</field>
    <field name="text">Very long text...</field>
</doc>

4 个答案:

答案 0 :(得分:1)

这是一个合理的答案,因为它使用了XML专用工具。

#!/bin/bash

function transform() {

  {
  cat  <<-'EOF'
    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

    <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />



    <xsl:output method="xml" encoding="UTF-8"/>

    <xsl:template match="/DOC">
    <doc> 
      <xsl:apply-templates  />
    </doc>
    </xsl:template>

    <xsl:template match="*">
    <field> 
    <xsl:attribute name="name"><xsl:value-of select="translate(local-name(),$uppercase,$lowercase)"/></xsl:attribute>
    <xsl:apply-templates />
    </field>
    </xsl:template>



    </xsl:stylesheet>
EOF
  } |  xsltproc - $1 

}


transform $1

这是我运行您的输入时得到的输出:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <field name="docid">MF-20020103001</field>
    <field name="date">01/03/02</field>
    <field name="title">Example title</field>
    <field name="text">Very long text...</field>
</doc>

编辑:我更改了上面的程序,将大写的元素名称转换为小写。信誉来自How can I convert a string to upper- or lower-case with XSLT?

的Jon W

答案 1 :(得分:0)

通常的建议是,如果可以依靠示例中给出的结构,则最好使用xml解析器来解析xml:

$ awk 'BEGIN { FS = "<|>"; OFS = ""} NF > 3 { $0 = "    <field name=\"" tolower($2) "\">"$3"</field>" }1' file
<?xml version="1.0" encoding="UTF-8"?>
<DOC>
    <field name="docid">MF-20020103001</field>
    <field name="date">01/03/02</field>
    <field name="title">Example title</field>
    <field name="text">Very long text...</field>
</DOC>

答案 2 :(得分:0)

这是一个很糟糕的答案,但需要完善:

sed -e "s/<\([^/>]*\)>/<field name='\1'>/g" -e "s/<\/\([^.]*\)>/<\/field>/" 

以下是您输入的输出内容:

<field name='?xml version="1.0" encoding="UTF-8"?'>
<field name='DOC'>
    <field name='DOCID'>MF-20020103001</field>
    <field name='DATE'>01/03/02</field>
    <field name='TITLE'>Example title</field>
    <field name='TEXT'>Very long text...</field>
</field>

您可以看到我的答案存在明显的问题:

  1. ?xml指令被击中
  2. 元素已修改
  3. 我们没有小写属性
  4. 我们可能会弄乱其他具有属性的元素(例如上面的?xml)

您获得的第一个建议是最好的。使用XML解析器。如果需要,您可以使用XSLT。然后,您可以生成XML样式表(.xsl)来定义转换。

答案 3 :(得分:0)

您可以使用任何XSLT-1.0处理器(例如m.allAccess)将输入XML转换为所需的输出XML。

这是可能的XSLT-1.0文件:

xsltproc

哪个输出是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/DOC">
      <doc>
        <xsl:apply-templates select="node()|@*" />
      </doc>
    </xsl:template>

    <xsl:template match="*">
      <field name="{translate(local-name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')}">
        <xsl:value-of select="text()" />
      </field>
    </xsl:template>

</xsl:stylesheet>

您可以使用XSLT处理器<?xml version="1.0" encoding="UTF-8"?> <doc> <field name="docid">MF-20020103001</field> <field name="date">01/03/02</field> <field name="title">Example title</field> <field name="text">Very long text...</field> </doc> 来获取此信息:

xsltproc