Как эффективно искать / заменять определенные строки в файле в Perl? - PullRequest
1 голос
/ 11 ноября 2011

Мой файл выглядит так:

<MAIN>  
  <SUB_MAIN>one</SUB_MAIN>  
  <VER>version#</VER>  
  (OTHER STUFF...)  
  <LOCATION>PATH</LOCATION>  
</MAIN>

<MAIN>  
  <SUB_MAIN>two</SUB_MAIN>  
  <VER>version#</VER>  
  (OTHER STUFF...)  
  <LOC>PATH</LOC>  
</MAIN>

То, что я хочу сделать, - это найти значение SUB_MAIN, скажем, один, и если я его найду, то искать значение LOCATION. Перейдите в это место, выполните синхронизацию, получите новую версию и обновите информацию VER.

Мой текущий код имеет три цикла и выглядит ужасно. Скелет выглядит так:

$value = "one|two|three";

# for each line in file
while ($line < @FileDat) {

    # see if it is a sub module?   
    if ( $line =~ /\<SUB_MAIN\>$value\<\/SUB_MAIN\>/ ) 
    {   
       $found_it = 0;

        while (!$found_it) 
        {       
            $lineNum++;     
            if ( $FileDat[$lineNum] =~ /\<VER\>\d+\<\/VER\>/ ) 
            {
                $currIndex = $lineNum;

                while(1)
                {
                   $lineNum++;
                   if ( $FileDat[$lineNum] =~ /\<LOC\>(.+)\<\/LOC\>/ ) 
                    {   #DO SOME STUFF...
                        $found_it = 1;
                        last;
                    }
                }               
                        #replace version #
                $FileDat[$currIndex] = "    <VER>$latestChangeList</VER>\n";
            }
        }
    }
    $lineNum++;
}

# write the modified array to new file
print NEWCFGFILEPTR @FileDat;

close(OPEN_FILES);

Как мне сделать это лучше?
Спасибо.

Ответы [ 3 ]

1 голос
/ 11 ноября 2011

Использовать XML :: Simple . Нет необходимости изобретать велосипед, если только вы не планируете его улучшить, и я очень сомневаюсь, что это ваша задача.

1 голос
/ 12 ноября 2011

На самом деле, использование синтаксического анализатора XML немного сложнее, чем просто использование модуля XML, поскольку то, что у вас есть, НЕ является правильно сформированным XML. Правильно сформированный XML-файл будет иметь один корень, поэтому все элементы MAIN будут заключены в один элемент.

Однако существует относительно простой способ его подделки, заключающийся в том, чтобы обернуть ваш файл, на который ссылается сущность XML, в соответствующий высокоуровневый элемент.

Кроме того, в данных вашего примера у вас есть элемент LOCATION в первой MAIN, затем элемент LOC во второй MAIN, я предполагаю, что это ошибка cut'n paste.

Вот способ сделать это с XML :: Twig, который будет работать с входным файлом любого размера (включая большой, чтобы уместиться в памяти), и который будет выводиться на стандартный вывод.

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

binmode( STDOUT, ':utf8'); # if your input file is in UTF-8

my $file= shift @ARGV;
# wrap the content of the file in <data>...</data> so it becomes well-formed XML
my $xml= qq{<?xml version="1.0"?>
            <!DOCTYPE data [ <!ENTITY file SYSTEM "$file">]>
            <data>&file;</data>
           };

XML::Twig->new( twig_handlers => { MAIN => \&main },
                keep_spaces => 1,
              )
         ->parse( $xml);

exit;

sub main
  { my( $t, $main)= @_;
    my $location= $main->field( 'LOCATION');
    $main->set_field( VER => get_version( $location));
    $main->print;
    $main->purge; # if the file is big and you want to free the memory
  }

sub get_version
  { my( $location)= @_;
    return "new.version.$location"; # the real code might be different!
  }

Если ваш входной файл НЕ в UTF-8, вам может потребоваться изменить оболочку, чтобы добавить правильную кодировку в объявление XML. Если в чистом виде используется ASCII, то у вас все хорошо (и при добавлении символов UTF-8 все равно будет работать).

Если вы не хотите использовать XML :: Twig, тот же метод применяется для создания правильного XML, который может быть прочитан XML :: Simple или любым другим модулем, который вы хотите использовать.

0 голосов
/ 11 ноября 2011

У вас есть файл XML. Вместо того, чтобы анализировать это с помощью регулярных выражений (что обычно считается плохой идеей), попробуйте использовать один из существующих модулей синтаксического анализа XML, например XML :: Parser . Есть много подобных модулей, которые вы можете найти, выполнив поиск xml на search.cpan.org , но это хороший.

...