我正在尝试删除位于标记之间的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代码并没有弄乱任何其他块。
有什么建议吗?
答案 0 :(得分:7)
通过进行两项更改,您的单行将完成您想要的任务:
if
更改为while
。g
选项添加到正则表达式:/.../gs
或者,看起来感兴趣的起始和结束标记本身在不同的行上。如果是这样,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_grep2
或xml_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
为了便于阅读,我添加了换行符。如果你真的是一个真正的单行班轮,你可以删除它们,虽然它也适用于换行符。