首页 > 解决方案 > 将前导零添加到特殊标签之间的数字

问题描述

我知道将前导零添加到数字并不复杂。但是,我正在寻找一种最佳解决方案,仅将前导零添加到介于两者之间的值<SpecialTag>0</SpecialTag>以使它们成为 5 位数字。

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
<Root>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>0</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>12</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>12345</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>1234</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
</Root>

预期结果应如下所示:

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
<Root>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>00000</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>00012</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>12345</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
    <Row>
        <Tag1>0</Tag1>
        <SpecialTag>01234</SpecialTag>
        <Tag2>0</Tag2>
    </Row>
</Root>

标签: bashshellsedxmlstarlet

解决方案


使用xsltproc建议的解决方案!):

拥有 XLST 文件transform.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

    <!-- Matches the SpecialTag -->
    <xsl:template match="SpecialTag">
        <xsl:copy>
            <!-- The number is available using node() and format-number() applies the 0-padding -->
            <xsl:value-of select="format-number(node(), '00000')" />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

input.xml如果包含您的 XML ,请运行以下命令:

$ xsltproc transform.xml input.xml

不安全的解决方案:

这些依赖于这样一个事实,即开始标签<SpecialTag>和结束标签</SpecialTag>在同一行,并且每行只有一个。

提及以下解决方案,因为作者使用 / / 明确标记了该问题。这些不是完成这项工作的正确工具

它们都使用正则表达式来 catch <SpecialTag>,然后是几个数字,然后用这些数字</SpecialTag>的 0 填充版本转换捕获的数字。

使用sed

sed --regexp-extended 's@<SpecialTag>([0-9]+)</SpecialTag>@<SpecialTag>0000000\1</SpecialTag>@;s@0*([0-9]{5,})@\1@'

使用perl

perl -pe 's@<SpecialTag>([0-9]+)</SpecialTag>@sprintf("<SpecialTag>%05d</SpecialTag>",$1)@e'

使用awk

awk '{gsub( /<SpecialTag>[0-9]+<\/SpecialTag>/, sprintf("<SpecialTag>%05d</SpecialTag>", gensub(/[^0-9]/, "","g"))); print}'

推荐阅读