perl one liner从xml文件中获取所有“键”

时间:2011-09-16 22:44:18

标签: regex perl

我正在尝试删除位于标记之间的XML文件中的所有行< KEYS>和< / KEYS>。

作为问题的第一步,我得到了一个正则表达式,它将与文件中的第一个键块匹配,但它不会继续匹配文件中的其他块。我已经尝试在正则表达式中添加“/ g”并且我尝试了“-0777”来立刻淹没整个文件,这两种技巧都没有任何区别。下面是perl one liner:

perl -00 -ne 'print $1 if /(\s+\<KEYS\>\n\s+.*?\n\s+\<\/KEYS\>)/s' someFile.xml

我得到了这个输出:

  <KEYS>
    <KEY name="cone_id" type="long" nativeType="number(17)"/>
    <KEY name="bar_id" type="long" nativeType="number(32)"/>
    <KEY name="foo_type" type="int" nativeType="number(3)"/>
  </KEYS>

如上所述,文件中有更多的块(长度接近五千行),但perl代码并没有弄乱任何其他块。

有什么建议吗?

5 个答案:

答案 0 :(得分:7)

通过进行两项更改,您的单行将完成您想要的任务:

  1. if更改为while
  2. g选项添加到正则表达式:/.../gs
  3. 或者,看起来感兴趣的起始和结束标记本身在不同的行上。如果是这样,flip-flop operator可能很方便:

    perl -ne 'print if m{<KEYS>} .. m{</KEYS>}' DATA_FILE
    

答案 1 :(得分:5)

我不完全确定你的意思是“剥离所有的线条”。如果你想要打印所有的KEYS元素而不打印其他元素,那么请到这里:

perl -MXML::Simple -e 'print XMLout((XMLin(join "", <>))->{KEYS})' data.xml    

或:

use XML::Simple;
my $xml = XMLin(join '', <DATA>); 
print XMLout($xml->{KEYS});

__DATA__
<root>
  <KEYS>
    <KEY name="cone_id" type="long" nativeType="number(17)"/>
    <KEY name="bar_id" type="long" nativeType="number(32)"/>
    <KEY name="foo_type" type="int" nativeType="number(3)"/>
  </KEYS>
  <NOTKEYS1>
    <KEY name="cone_id" type="long" nativeType="number(17)"/>
    <KEY name="bar_id" type="long" nativeType="number(32)"/>
    <KEY name="foo_type" type="int" nativeType="number(3)"/>
  </NOTKEYS1>
  <NOTKEYS2>
    <KEY name="cone_id" type="long" nativeType="number(17)"/>
    <KEY name="bar_id" type="long" nativeType="number(32)"/>
    <KEY name="foo_type" type="int" nativeType="number(3)"/>
  </NOTKEYS2>
  <KEYS>
    <KEY name="cone_id" type="long" nativeType="number(17)"/>
    <KEY name="bar_id" type="long" nativeType="number(32)"/>
    <KEY name="foo_type" type="int" nativeType="number(3)"/>
  </KEYS>
</root>

即使你根本不关心结构,这比正则表达式更容易推理,不是吗?

无论如何,这是一个正则表达式版本:

perl -e '$a = join "", <>; print $a =~ m/(\s+\<KEYS\>\n\s+.*?\n\s+\<\/KEYS\>)/sg' data.xml

答案 2 :(得分:4)

如果XML格式正确,您可以在XML::Twig中使用xml_grep附带的xml_grep2xml_grep -v KEYS to_strip.xml xml_grep2 -v '//KEYS' to_strip.xml

{{1}}

第一个基于XML :: Twig并以流模式工作,第二个基于XML :: LibXML并在开始grep之前将整个文档加载到内存中,但它应该更快(我没有'但是对它进行了基准测试。)

这两个都不是Perl one liner,但它们都是用Perl编写的,所以我希望你能接受它; - )

答案 3 :(得分:0)

你必须使用perl吗?如果没有,请尝试sed:

sed -i".backup" 's/<KEYS>([^<]*)<\/KEYS>/\1/g' somefile.xml

答案 4 :(得分:0)

perl -MXML::LibXML -e'
   my $doc = XML::LibXML->new->parse_file($ARGV[0]);
   $_->parentNode->removeChild($_)
      for $doc->documentElement->findnodes("//KEYS");
   $doc->toFile($ARGV[1], 0);
' infile outfile

为了便于阅读,我添加了换行符。如果你真的是一个真正的单行班轮,你可以删除它们,虽然它也适用于换行符。