【问题标题】:Delete multiple lines from a file by finding a key [closed]通过查找密钥从文件中删除多行 [关闭]
【发布时间】:2015-03-13 13:15:57
【问题描述】:

假设我在一个文件中有以下几行(不要认为它是一个 XML 文件):

<AVP code="123" name="abcd">
    <type>
        <high/>
    </type>
</AVP>
<AVP code="234" name="ukbkj">
    <type>
      <enum/>
    <type>
       <enum name="erdf"/>
 </AVP>

我想从(例如)AVP 代码 123 删除到匹配的 /AVP,以便删除 AVP 123 的所有数据。我怎样才能做到这一点? 这是输出的样子。我想保存到文件,而不是打印到标准输出。

<AVP code="234" name="ukbkj">
    <type>
       <enum/>
    <type>
       <enum name="erdf"/>
 </AVP>

【问题讨论】:

  • 我不太明白。请在您的问题中包含 1) 所需的输出,2) 您尝试过的 Python 或 Perl 代码,3) 您得到的实际输出。
  • 他试图删除整个区块。
  • 我需要python脚本
  • 这不应该是 XML 吗?是&lt;high\&gt; 还是&lt;high/&gt;?文档有根元素吗?
  • 你真的认为有人会因为你他而支持你的问题吗?如果人们认为您的问题显示了研究成果并且有用且清晰,您将获得支持。它没有,也不是。

标签: python perl shell


【解决方案1】:

通过 perl。

$ perl -0777pe 's/<AVP code="123".*?<\/AVP> *\n//sg' file
<AVP code="234" name="ukbkj">
<type>
<enum\>
<type>
<enum\>
<AVP code>

通过python。

import re
with open('file') as f:
    m = f.read()
    splt = re.findall(r'(?s)<AVP\s+code="\d+".*?</AVP>', m)
    for i in splt:
        if '<AVP code="123"' not in i:
            print(i, end="")

【讨论】:

  • 也许它应该寻找一个结束的&lt;/AVP&gt;标签而不是下一个AVP元素:如果他要删除的那个是序列中的最后一个呢?这不会吞噬文档的所有其余部分吗?
  • 更好;猜猜OP想要python,即使他把perl标签放在上面......
  • 如果有人也能在 perl 脚本中分辨出来,那就太好了。这将有助于了解 perl,这就是为什么我还要加上 perl 和 shell 标记.. @EricHughes
  • 还添加了python代码。
  • 我怀疑。从他上面的 cmets 我得到的印象是他甚至不知道 XML 语法。
【解决方案2】:

如果您的输入是 XML,它看起来像这样:

<?xml version="1.0"?>
<root>
    <AVP code="123" name="abcd">
        <type>
            <high/>
        </type>
    </AVP>
    <AVP code="234" name="ukbkj">
        <type>
          <enum/>
        </type>
        <type>
           <enum/>
        </type>
     </AVP>
</root>

您可以使用此 XSLT 删除所有 AVP 元素。

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

 <xsl:output omit-xml-declaration="no"/>

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

    <xsl:template match="AVP[@code='123']" />
</xsl:stylesheet>

使用 Python 应用它:

import lxml.etree as ET

dom = ET.parse("avp.xml")
xslt = ET.parse("avp.xslt")
transform = ET.XSLT(xslt)
newdom = transform(dom)
with open("avp-out.xml", "wb") as o:
    o.write(ET.tostring(newdom, pretty_print=True))

avp-out.xml 中的输出:

<root>

    <AVP code="234" name="ukbkj">
        <type>
          <enum/>
        </type>
        <type>
           <enum/>
        </type>
     </AVP>
</root>

【讨论】:

  • 正如您使用 xslt 向我解释的那样。但代码可能不同(用户会询问)所以这里我们如何将用户输入代码传递给 xslt。
【解决方案3】:

更合适的方法是使用 XML 解析库,XML::LibXML 是一个很好的方法。请注意,您当前的示例是 not 有效的 XML:

use strict; 
use warnings; 

use XML::LibXML;

my $xml_filename = $ARGV[0];
die "Missing name of xml file to parse"
   unless $xml_filename;
open(my $xml_file, '<', $xml_filename) 
   or die "Error opening XML file: $!";

my $dom = XML::LibXML->load_xml(IO => $xml_file);
foreach my $node ( $dom->findnodes('/root/AVP') ) {
   $node->unbindNode()
      if $node->getAttribute('code') == 123;
}

open(my $out_fh, '>', "${xml_filename}.out") 
   or die "Unable to open outfile: $!";
binmode $out_fh;    

# write XML tree to file
$dom->toFH($out_fh);
close($out_fh);

【讨论】:

    【解决方案4】:

    使用XML::Twig - 复制 Lutz Horn 提到的固定 XML:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use XML::Twig;
    
    sub delete_if_code_123 {
        my ( $twig, $AVP ) = @_;
        if ( $AVP->att('code') eq "123" ) {
            $AVP->delete;
        }
    }
    
    my $twig = XML::Twig->new(
        pretty_print  => 'indented',
        twig_handlers => { 'AVP' => \&delete_if_code_123 },
    );
    
    $twig ->parse( \*DATA );
    
    $twig -> print;
    
    
    __DATA__
    <?xml version="1.0"?>
    <root>
        <AVP code="123" name="abcd">
            <type>
                <high/>
            </type>
        </AVP>
        <AVP code="234" name="ukbkj">
            <type>
              <enum/>
            </type>
            <type>
               <enum/>
            </type>
         </AVP>
    </root>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      相关资源
      最近更新 更多