Perl, совпадение с одним шаблоном несколько раз в одной строке, разделенной неизвестными символами - PullRequest
7 голосов
/ 06 февраля 2012

Мне удалось найти похожие, но не идентичные вопросы к этому.Как мне сопоставить один шаблон регулярного выражения несколько раз в одной строке, разделенной неизвестными символами?

Например, скажем, я хочу сопоставить шаблон HEY.Я хотел бы распознать все следующее:

HEY

HEY HEY

HEYxjfkdsjfkajHEY

Так что я считаю5 ЭЙ там.Итак, вот моя программа, которая работает для всего, кроме последней:

open ( FH, $ARGV[0]);
while(<FH>)
{
  foreach $w ( split )
  {
      if ($w =~ m/HEY/g)
      {
            $count++;
      }
  }
}

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

РЕДАКТИРОВАТЬ:

Спасибо за большой отклик до сих пор.Я только что понял, что мне нужна еще одна вещь, которую я поместил в комментарии ниже.

Один вопрос, хотя: есть ли способ также сохранить соответствующий термин?Как и в моем случае, есть ли способ сослаться на $ w (скажем, если регулярное выражение было более сложным, и я хотел сохранить его в хэше с количеством вхождений)

Так что если ясоответствовал реальному регулярному выражению (скажем, последовательности буквенно-цифровых символов) и хотел сохранить его в хэше.

Ответы [ 3 ]

11 голосов
/ 06 февраля 2012

Один из способов - захватить все совпадения строки и посмотреть, сколько у вас получилось.Вот так:

open (FH, $ARGV[0]);
while(my $w = <FH>) {
    my @matches = $w =~ m/(HEY)/g;
    my $count = scalar(@matches);
    print "$count\t$w\n";
}

РЕДАКТИРОВАТЬ:

Да, есть!Просто зациклите все совпадения и используйте переменные захвата для увеличения числа в хэше:

my %hash;
open (FH, $ARGV[0]);
while (my $w = <FH>) {
   foreach ($w =~ /(HEY)/g) {
       $hash{$1}++;
   }
}
5 голосов
/ 06 февраля 2012

Проблема в том, что вы действительно не хотите вызывать split ().Он разбивает вещи на слова, и вы заметите, что ваша последняя строка содержит только одно слово (хотя вы не найдете его в словаре).Слово ограничено пробелом и, таким образом, это просто «все, кроме пробелов».

Что вам действительно нужно, так это продолжать просматривать каждую строку, считая каждый HEY, начиная с того места, где вы остановились каждый раз.Что требует / g в конце, но для продолжения поиска:

while(<>)
{
      while (/HEY/g)
      {
            $count++;
      }
}

print "$count\n";

Конечно, есть несколько способов сделать это, но это соответствует вашему примеру.Другие люди будут публиковать другие замечательные примеры тоже.Учитесь у них всех!

0 голосов
/ 14 февраля 2014

Ни один из приведенных выше ответов не помог мне. $ 1, похоже, не меняется (perl 5.16.3), поэтому $ hash {$ 1} ++ просто посчитает первое совпадение n раз.

Чтобы получить каждое совпадение, foreach требуется назначенная локальная переменная, которая затем будет содержать переменную совпадения. Вот небольшой скрипт, который будет сопоставлять и печатать каждое вхождение (число).

#!/usr/bin/perl -w                                                                                                                    
use strict;
use warnings FATAL=>'all';

my (%procs);
while (<>) {

    foreach my $proc ($_ =~ m/\((\d+)\)/g) {
        $procs{$proc}++;
    }

}

print join("\n",keys %procs) . "\n";

Я использую это так:

pstree -p | perl extract_numbers.pl | xargs -n 1 echo

(за исключением некоторых соответствующих фильтров в этом конвейере). Любой захват образца должен также работать.

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