Почему первое значение захваченного выражения хранится в четвертом элементе в Perl? - PullRequest
0 голосов
/ 02 августа 2009

Я храню информацию, захваченную регулярным выражением, в массив. Но по какой-то причине первое значение хранится в 4 элементах массива. Любое предложение о том, что происходит не так и как сохранить первое значение в первом элементе массива.

Следующий скрипт:

#!/usr/bin/perl

use strict;
my @value;
my $find= qr/^\s+([0-9]+)\s+([A-Z])/;

open (FILE, "</usr/test")|| die "cant open file";
my @body=<FILE>;

foreach my $line (@body){
    chomp $line;
    push @value, join('', $line =~ /$find/);
}
print "$value[0]\n"; #does not print anything
print "$value[4]\n"; #prints first value i.e 1389E
exit;

DATA

   1389 E not
   188  S yes
   24   D yes
   456  K not
   2    Q yes   

Ответы [ 4 ]

4 голосов
/ 02 августа 2009

Ваша вторая строка имеет более одного пробела между группой чисел и буквой, поэтому вы, вероятно, хотите \s+ оба раза вместо \s во второй раз.

Вы не обязательно будете знать, сколько элементов у вас в массиве @value в конце, поэтому вы можете поместить печать в цикл for, а не предполагать, что у вас есть пятый элемент. (Может быть, вы знаете, что хотите первый и пятый, однако?) Последующие действия : в зависимости от ваших правок у вас есть более двух записей. Версия, которую я даю ниже, используя split и \s+, фиксирует число и букву для всех строк. Я настрою печатную часть сценария, чтобы показать вам, что я имею в виду.

Несколько других вещей:

  • Вы должны всегда включать предупреждения.
  • Нет причин читать весь файл в массив, а затем обрабатывать его построчно. Пропустите массив @body и просто сделайте то, что вам нужно в цикле while.
  • Используйте более современную форму open с лексическими дескрипторами файлов и тремя аргументами.
  • split здесь мне кажется более простым, нежели регулярное выражение со снимками. Поскольку вы хотите захватить две определенные части строки, вы можете использовать split с фрагментом массива, чтобы захватить эти два элемента и передать их в join.
  • @value - не особо полезное имя переменной, но я думаю, что вы должны хотя бы сделать его множественным. Думаю, это хорошая привычка, поскольку в массиве хранятся ваши множественные записи. (Это не жесткое и быстрое правило, но оно меня здесь напугало. Этот момент довольно незначительный.)

Вот как все это может выглядеть:

    #!/usr/bin/env perl
    use warnings;
    use strict;

    my @values;

    # open my $filehandle, '<', '/usr/test'
    #     or die "Can't open /usr/test: $!";

    while (my $line = <DATA>) {
        chomp $line;
        push @values, join('', (split /\s+/, $line)[1..2]);
    }

   for my $record (@values) {
      print $record, "\n";
    }

    __DATA__
       1389 E not
       188  S yes
       24   D yes
       456  K not
       2    Q yes
1 голос
/ 02 августа 2009

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

В любом случае наиболее вероятной причиной вашей проблемы является отсутствие одного символа в вашем шаблоне. Сравните тот, что ниже, с тем, который у вас есть выше.

#!/usr/bin/perl

use strict;
use warnings;

my @value;
my $find= qr/^\s+([0-9]+)\s+([A-Z])/;

while ( my $line = <DATA> ) {
    last unless $line =~ /\S/;
    push @value, join '', $line =~ $find;
}

use Data::Dumper;
print Dumper \@value;

__DATA__
   1389 E not
   188  S yes
   24   D yes
   456  K not
   2    Q yes
1 голос
/ 02 августа 2009

Я думаю, вы должны писать

print "$value[0]\n";
print "$value[4]\n";

для доступа к элементам массива.

0 голосов
/ 03 августа 2009

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

Обратите внимание:

#!/usr/bin/perl

use strict;
use warnings;

my @lines;

while (<DATA>) {
  push @lines , ( join( '' , /^\s*(\d+)/ ));
}

foreach ( 0 .. $#lines ) {
  print "$_ -> $lines[$_]\n";
}


__DATA__
FOO
Bar
Baz
   1234
456
bargle

Выход:

0 -> 
1 -> 
2 -> 
3 -> 1234
4 -> 456
5 -> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...