Especifique um ponto de partida para encontrar e substituir unix, depois incrementar

1

Estou fazendo uma renumeração de um atributo de referência em um arquivo xml. O atributo é, por exemplo, data-seq="1" . Eu já posso renumerar esse atributo em todos os arquivos usando isso:

find $DATA_PATH/content/*.xml -exec perl -pi -e 's/data-seq="[0-9]+(?=")/qq(data-seq=").++$n/ge' {} +

Isso funciona muito bem. No entanto, gostaria de adicionar um ponto de partida. Por exemplo, inicie a renumeração em data-seq="125" e, em seguida, suba a partir daí. Isso é possível?

Aqui está um exemplo de alguns dos xml (apenas um pequeno snippet que mostra o atributo em questão e algumas outras tags):

<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...

O que eu gostaria de fazer é ignorar tudo antes de 125 e começar a renumerar, em 126, em todos os arquivos depois que ele encontrar data-seq="125". Isso é para corrigir problemas em que esse atributo, que deve ser seqüencial, tenha lacunas ou se repita nele, o que elimina todos os outros números após o intervalo ou a repetição.

Eu não preciso verificar a integridade estrutural da marcação ou algo assim, apenas incrementar a numeração.

Estes são todos os arquivos de texto unix, a propósito.

Obrigado.

    
por Mike 30.09.2015 / 18:43

1 resposta

2

Sem algum exemplo de XML, isso é difícil. Eu recomendo strongmente NÃO usar expressões regulares, porque as expressões regulares realmente não fazem XML muito bem.

Eu provavelmente abordaria isso assim:

#!/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>

Transforma a nossa saída em:

<xml>
  <test data-seq="125" />
  <test some-other="fish" />
  <test data-seq="126" />
</xml>

E combine-o com File::Find para fazer isso em todos os arquivos desejados.

Algo parecido com isto:

#!/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" );
    
por 30.09.2015 / 19:07