使用CygWin在txt文件中插入新行

时间:2018-08-17 12:34:35

标签: xml unix awk sed cygwin

我有一个XML表,其行结构如下:

<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>foobar</C3>
    <C4>foobar</C4>
    <C5>foobar</C5>
    <C6>foobar</C6>
    <C7>foobar</C7>
    <C8>foobar</C8>
    <C9>foobar</C9>
    <C10>foobar</C10>
    <C11>foobar</C11>
    <C12>foobar</C12>
</row>

我想做的是在第12列之后添加第13列,该列需要有一个递增的数字作为其值,以用作主键(从1开始,每行增加1,例如X ++等等) 。值得注意的是,大约有2000万行。

我一直在尝试使用CygWin(Mintty)进行此操作,但是我对此完全没有经验,也没有任何Unix的经验,这只是我所建议的第一件事,它实际上能够加载这些怪异的XML。文件。

对于初学者,我尝试使用 Sed 通过以下命令插入第13列:

-i -e 's/\/C12>/\/C12><C13><\/C13>/g' t1s.txt

我的想法是,我将用自己的C13支架和第13列代替。相反,它只是将C12替换为C13,好像没有正确地转义斜线一样。

可能有一个命令“插入”而不是“替换”,这使我正在尝试做的事情看起来完全疯狂,但我不知道该命令将是什么,并且没有太多运气。如果Sed无法实现此功能,我最想使用的是AWK,但我不知道该怎么做,但我也不知道该怎么做,而且似乎也很难。

我希望实现的是按如下方式更改文档(很长,但显然不包括所有内容就没有意义。这个问题仅涉及如何在每行中添加第13列,即其他12个只是上下文):

<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>foobar</C3>
    <C4>foobar</C4>
    <C5>foobar</C5>
    <C6>foobar</C6>
    <C7>foobar</C7>
    <C8>foobar</C8>
    <C9>foobar</C9>
    <C10>foobar</C10>
    <C11>foobar</C11>
    <C12>foobar</C12>
    <C13>1</C13>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>foobar</C3>
    <C4>foobar</C4>
    <C5>foobar</C5>
    <C6>foobar</C6>
    <C7>foobar</C7>
    <C8>foobar</C8>
    <C9>foobar</C9>
    <C10>foobar</C10>
    <C11>foobar</C11>
    <C12>foobar</C12>
    <C13>2</C13>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>foobar</C3>
    <C4>foobar</C4>
    <C5>foobar</C5>
    <C6>foobar</C6>
    <C7>foobar</C7>
    <C8>foobar</C8>
    <C9>foobar</C9>
    <C10>foobar</C10>
    <C11>foobar</C11>
    <C12>foobar</C12>
    <C13>3</C13>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>foobar</C3>
    <C4>foobar</C4>
    <C5>foobar</C5>
    <C6>foobar</C6>
    <C7>foobar</C7>
    <C8>foobar</C8>
    <C9>foobar</C9>
    <C10>foobar</C10>
    <C11>foobar</C11>
    <C12>foobar</C12>
    <C13>4</C13>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>foobar</C3>
    <C4>foobar</C4>
    <C5>foobar</C5>
    <C6>foobar</C6>
    <C7>foobar</C7>
    <C8>foobar</C8>
    <C9>foobar</C9>
    <C10>foobar</C10>
    <C11>foobar</C11>
    <C12>foobar</C12>
    <C13>5</C13>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>foobar</C3>
    <C4>foobar</C4>
    <C5>foobar</C5>
    <C6>foobar</C6>
    <C7>foobar</C7>
    <C8>foobar</C8>
    <C9>foobar</C9>
    <C10>foobar</C10>
    <C11>foobar</C11>
    <C12>foobar</C12>
    <C13>6</C13>
</row>

这种情况持续了几百万行...

请注意,唯一的变化是增加了第13列,并且其值每行增加一次。这就是这个问题的全部,其他12列只是周围的结构。

3 个答案:

答案 0 :(得分:2)

使用xmlstarlet和XSLT转换:

提供此XSLT文件

$ cat f.xslt 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <!-- Identity transform -->
    <xsl:template match="/ | @* | node()">
            <xsl:copy>
                    <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
    </xsl:template>
    <xsl:template match="/">
            <xsl:for-each select="/doc/row">
                    <xsl:copy>
                            <xsl:apply-templates select="@* | node()"/>
                            <C13><xsl:value-of select="position()"/></C13>
                    </xsl:copy>
            </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

并假设<row>...</row>包含在标签<doc>...</doc>中,您可以使用以下命令将C13节点及其计数添加到其中:

xmlstarlet tr f.xslt file

tr的意思是“转置”,并使用XSLT文件修改给定的file

XSLT主要包含2个块。
一种称为“身份”的方式,将输入保持原样。第二个块查找每个<doc><row>并复制其内容,并向<C13>节点添加计数。

积分:herehere

答案 1 :(得分:1)

要编辑XML文件,最好使用XML解析器。

以下是使用C13(在Cygwin中可用)将包含文本foobar的节点xmlstarlet插入XML文件的命令:

xmlstarlet ed --subnode "/row" -t elem -n C13 -v foobar ts1.txt
  • ed:编辑/更新XML文档
  • --subnode "/row":在row节点内添加一个节点
  • -t elem:类型为元素
  • -n C13:名称为C13
  • v foobar:值是foobar

答案 2 :(得分:0)

如果您的输入确实是那么常规和简单,那么您所需要的就是:

awk '{print} sub(/<C12>.*/,""){print $0"<C13>"++cnt"</C13>"}' file

,但没有具体的依据来检验其猜测。这就是我认为的操作,您正在尝试使用每个块有2个foobar而不是12个foobar的MCVE:

$ cat file
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
</row>

$ awk '{print} sub(/<C2>.*/,""){print $0"<C3>"++cnt"</C3>"}' file
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>1</C3>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>2</C3>
</row>
<row>
    <C1>foobar</C1>
    <C2>foobar</C2>
    <C3>3</C3>
</row>

请注意,数字12和13可以根据您的输入进行调整,它们不需要在脚本中对top进行硬编码,但是如果需要则可以使用idk,因此我不必理会。