我正在对 xml 文件中的引用属性进行重新编号。该属性例如是data-seq="1"
。我已经可以使用以下命令在所有文件中重新编号该属性:
find $DATA_PATH/content/*.xml -exec perl -pi -e 's/data-seq="[0-9]+(?=")/qq(data-seq=").++$n/ge' {} +
这很好用。不过我想添加一个起点。例如,从 data-seq="125" 开始重新编号,然后从那里向上。那可能吗?
下面是一些 xml 的示例(只是一个小片段,显示了相关属性和一些其他标签):
<b>Reconciliation</b>
<p>As often happens, just as one is beginning to find a solution <span class="page" title="20" data-seq="34"/>to a particular problem the problem becomes less pressing or ceases to exist.</p>
<span class="page" title="21" data-seq="35"/>
<b>The Multi-Plant Enterprise</b>
<p>The MNE is...
我想做的是忽略 125 之前的所有内容,并在找到 data-seq="125" 后开始在所有文件中从 126 重新编号。这是为了解决该属性(应该是连续的)中存在间隙或重复的问题,从而导致间隙或重复之后的所有其他数字都被丢弃。
我不需要检查标记的结构完整性或类似的内容,只需增加编号即可。
顺便说一句,这些都是 UNIX 文本文件。
谢谢。
答案1
如果没有一些 XML 示例,这很难。我强烈建议不要使用正则表达式,因为正则表达式确实不能很好地处理 XML。
我可能会这样处理:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $start_renumber = 125;
my $twig = XML::Twig -> new ( pretty_print => 'indented_a' ) -> parse ( \*DATA );
foreach my $test_elt ( $twig -> findnodes ( '//test[@data-seq]' ) ) {
$test_elt -> set_att('data-seq', $start_renumber++ );
}
$twig -> print;
__DATA__
<xml>
<test data-seq="999" />
<test some-other="fish" />
<test data-seq="123125" />
</xml>
将我们的输出变成:
<xml>
<test data-seq="125" />
<test some-other="fish" />
<test data-seq="126" />
</xml>
并将其与File::Find
您想要的所有文件结合起来执行此操作。
像这样的东西:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use File::Find;
my $start_renumber = 125;
sub update_data_seq {
my ( $twig, $element ) = @_;
if ( $element -> att('data-seq') > 125 ) {
$element->set_att( 'data-seq', $start_renumber++ );
}
}
sub process_xml {
next unless -f;
next unless m/\.xml/;
my $twig = XML::Twig->new(
pretty_print => 'indented_a',
twig_handlers => { '//span[@data-seq]' => \&update_data_seq }
);
$twig->parsefile_inplace($File::Find::name);
}
find( \&process_xml, "/path/to/search/for/xml",
"/some/other/path/if/you/want" );