Perl: получить подстроку, соответствующую ошибке регулярного выражения - PullRequest
1 голос
/ 08 апреля 2010

Я очень плохо знаком с Perl, поэтому, пожалуйста, ответьте на мой простой вопрос:

Вот пример вывода:

Most successful agents in the Emarket climate are (in order of success):
1.  agent10896761       ($-8008)
2.  flightsandroomsonly     ($-10102)
3.  agent10479475hv     ($-10663)
Most successful agents in the Emarket climate are (in order of success):
1.  agent10896761       ($-7142)
2.  agent10479475hv     ($-8982)
3.  flightsandroomsonly     ($-9124)

Меня интересуют только имена агентов и их соответствующие балансы, поэтому я надеюсь получить следующий вывод:

agent10896761       -8008
flightsandroomsonly     -10102
agent10479475hv     -10663
agent10896761       -7142
agent10479475hv     -8982
flightsandroomsonly     -9124

Для последующих процессов.

Это код, который я получил до сих пор:

#!/usr/bin/perl -w
open(MYINPUTFILE, $ARGV[0]);

while(<MYINPUTFILE>)
{
    my($line) = $_;
    chomp($line);

    # regex match test
    if($line =~ m/agent10479475/)
    {   
        if($line =~ m/($-[0-9]+)/)
        {
            print "$1\n";
        }

    }
    if($line =~ m/flightsandroomsonly/)
    {
        print "$line\n";
    }
}

Второе совпадение с регулярным выражением не имеет ничего плохого, потому что оно печатает всю строку. Тем не менее, для первого совпадения с регулярным выражением у меня есть некоторые другие выходные данные, такие как:

$ ./compareResults.pl 3.txt
2.      flightsandroomsonly             ($-10102)
0479475
0479475
3.      flightsandroomsonly             ($-9124)
1.      flightsandroomsonly             ($-8053)
0479475
1.      flightsandroomsonly             ($-6126)
0479475

Если я "убегу" от таких скобок, как это

if($line =~ m/\($-[0-9]+\)/)
{
    print "$1\n";
}

Тогда никогда не найдется соответствия для первого регулярного выражения ...

Так что я застрял с проблемой заставить этот конкретный регулярное выражение работать. Есть намеки на это? Большое спасибо заранее.

Ответы [ 3 ]

4 голосов
/ 08 апреля 2010

Помните, что $ в регулярном выражении является якорем в конце строки. Escape, чтобы соответствовать буквальному символу знака доллара.

Я бы написал так:

#! /usr/bin/perl

use warnings;
use strict;

# for demo only
*ARGV = *DATA;

my $agent = qr/
  ^ \s* \d+ \.   # item number at the beginning of line
  \s+
  (\S+)          # agent name into $1
  \s+
  \( \s* \$ \s*  # start of balance
  (-?\d+)        # balance into $2
  \s* \)         # end of balance
  \s* $          # optional whitespace at the tail
/x;
while (<>) {
  if (my ($name,$balance) = /$agent/) {
    printf "%-20s : %d\n", $name, $balance;
  }
}

__DATA__
Most successful agents in the Emarket climate are (in order of success):
1.  agent10896761       ($-8008)
2.  flightsandroomsonly     ($-10102)
3.  agent10479475hv     ($-10663)
Most successful agents in the Emarket climate are (in order of success):
1.  agent10896761       ($-7142)
2.  agent10479475hv     ($-8982)
3.  flightsandroomsonly     ($-9124)

Выход:

agent10896761        : -8008
flightsandroomsonly  : -10102
agent10479475hv      : -10663
agent10896761        : -7142
agent10479475hv      : -8982
flightsandroomsonly  : -9124

Не позволяйте линии *ARGV = *DATA напугать вас. Это позволяет мне объединить программу и ее ввод в одном файле без изменения логики обработки. В своем коде вы удалите эту строку, а затем запустите программу так же, как и раньше, например, ,

$ ./compareResults.pl input.txt
3 голосов
/ 08 апреля 2010
perl -ane '$F[2]=~s/\(|\)//g;print "$F[1] $F[2]\n" if $F[1]=~/agent|flight/' file
1 голос
/ 08 апреля 2010
use strict;
use warnings;

while(<DATA>){
    #split on whitespaces, pick 2nd and 3rd items
#check 2nd item matches pattern, do some trimming to 3rd
#store them to @data and print them
    my @data =grep{/\w{13,}/ || s/\(\$|\)//g;}((split' ')[1,2]);
    print join("\t",@data),"\n" if (@data);

}


__DATA__
1.  agent10896761       ($-8008)
2.  flightsandroomsonly     ($-10102)
3.  agent10479475hv     ($-10663)
Most successful agents in the Emarket climate are (in order of success):
1.  agent10896761       ($-7142)
2.  agent10479475hv     ($-8982)
3.  flightsandroomsonly     ($-9124)

__OUTPUT__
agent10896761   -8008
flightsandroomsonly     -10102
agent10479475hv -10663
agent10896761   -7142
agent10479475hv -8982
flightsandroomsonly     -9124
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...