проанализировать несколько строк в регулярном выражении Perl и извлечь значение - PullRequest
2 голосов
/ 15 декабря 2010

Я новичок в Perl. У меня есть текстовый файл с текстом, аналогичным приведенному ниже. Мне нужно извлечь VALUE = "<<strong> NEEDED VALUE >". Скажи за шпинат, я должен получить САЛАТ один.

Как использовать регулярные выражения Perl для получения значения. мне нужно разобрать несколько строк, чтобы получить его. то есть между каждым #ifonly --- # endifonly

$ cat check.txt

while (<$file>)
{
   if (m/#ifonly .+ SPINACH .+ VALUE=(")([\w]*)(") .+ #endifonly/g)
{
    my $chosen = $2;
   }
}


#ifonly APPLE CARROT SPINACH
VALUE="SALAD" REQUIRED="yes" 
QW RETEWRT OIOUR
#endifonly
#ifonly APPLE MANGO ORANGE CARROT
VALUE="JUICE" REQUIRED="yes" 
as df fg
#endifonly

Ответы [ 5 ]

5 голосов
/ 15 декабря 2010
use strict;
use warnings;
use 5.010;

while (<DATA>) {
   my $rc = /#ifonly .+ SPINACH/ .. (my ($value) = /VALUE="([^"]*)"/);
   next unless $rc =~ /E0$/;
   say $value;
}

__DATA__
#ifonly APPLE CARROT SPINACH
VALUE="SALAD" REQUIRED="yes" 
QW RETEWRT OIOUR
#endifonly
#ifonly APPLE MANGO ORANGE CARROT
VALUE="JUICE" REQUIRED="yes" 
as df fg
#endifonly

Здесь используется небольшой трюк, описанный Брайаном Д. Фой здесь .Как описывает ссылка, он использует скалярный оператор range / flipflop .

1 голос
/ 15 декабря 2010

Если ваш файл очень большой (или вы хотите прочитать его построчно по какой-то другой причине), вы можете сделать это следующим образом:

#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;

my ($file, $keyword);

# now get command line options (see Usage note below)
GetOptions(
            "f=s" => \$file,
            "k=s" => \$keyword,
          );

# if either the file or the keyword has not been provided, display a
# help text and exit
if (! $file || ! $keyword) {
   print STDERR<<EOF;

   Usage: script.pl -f filename -k keyword

EOF
   exit(1);
}

my $found;         # indicator that the keyword has been found
my $returned_word; # will store the word you want to retrieve

open FILE, "<$file" or die "Cannot open file '$file': $!";
while (<FILE>) {
   if (/$keyword/) {
      $found = 1;
   }

   # the following condition will be true between all lines that
   # start with '#ifonly' or '#endifonly' - but only if the keyword 
   # has been found!
   if (/^#ifonly/ .. /^#endifonly/ && $found) {
      if (/VALUE="(\w+)"/) { 
         $returned_word = $1;
         print "looking for $keyword --> found $returned_word\n";

         last; # if you want to get ALL values after the keyword
               # remove the 'last' statement, as it makes the script
               # exit the while loop
      }
   }
}
close FILE;
0 голосов
/ 18 декабря 2010

Эти две строки в одном ответе, данном два дня назад

my $file;
$file.=$_ while(<>);

, не очень эффективны.Perl, вероятно, будет читать файл большими кусками, разбивать эти куски на строки текста для <>, а затем .= соединит эти строки, чтобы создать большую строку.Было бы более эффективно, чтобы хлебать файл.Основной стиль - изменить \$ разделитель входной записи.

undef $/;
$file = <>;

Модуль File::Slurp; (см. perldoc File::Slurp) может быть даже лучше.

0 голосов
/ 16 декабря 2010

Вот еще один ответ, основанный на операторе триггера:

use strict;
use warnings;
use 5.010;

while (<$file>)
{
  if ( (/^#ifonly.*\bSPINACH\b/ .. /^#endifonly/) &&
       (my ($chosen) = /^VALUE="(\w+)"/) )
  {
    say $chosen;
  }
}

Это решение применяет второй тест к всем линиям в диапазоне.Трюк @Hugmeir, используемый для исключения начальных и конечных строк, не нужен, потому что «внутреннее» регулярное выражение /^VALUE="(\w+)"/ никогда не может соответствовать им (я добавил ^ якорь ко всем регулярным выражениям, чтобы вдвойне убедиться в этом).

0 голосов
/ 15 декабря 2010

Вы можете прочитать содержимое файла в строке, а затем найти шаблон в строке:

my $file;    
$file.=$_ while(<>);    
if($file =~ /#ifonly.+?\bSPINACH\b.+?VALUE="(\w*)".+?#endifonly/s) {
        print $1;
}

Ваше оригинальное регулярное выражение нуждается в доработке:

  • Вы должны сделать свои квантификаторы нежадным.
  • Используйте модификатор s, чтобы сделать . соответствует новой строке.

Ideone Link

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...