Захватить подстроку между двумя символами? - PullRequest
0 голосов
/ 30 июня 2018

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

default_checks/my_checks/VLG6.3: Unsupported system function call

Мне нужно захватить VLG6.3. Он находится между косой чертой / и двоеточием :.

Я попробовал эти идеи

my $rule = $line =~ /\/(.*)\:/;
my $rule = $line =~ /\/(.+?)\:/ ;
my $rule = $line =~ /\/(\w+)\:/ ; 

Но ни один из них не работает. В лучшем случае я получаю my_checks/VLG6.3

Ответы [ 4 ]

0 голосов
/ 30 июня 2018

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

my $line = 'default_checks/my_checks/VLG6.3: Unsupported system function call';
my ( $rule ) = $line =~ /\/([^\/:]*):/;
print "$rule\n";

PS: Для захвата содержимого между двумя строками необходимо пропустить последовательности начальной строки.

my $line = 'begin not this begin or this begin wanted end not this end or this end';
my ( $rule ) = $line =~ m{ (?: begin .* )? begin (.*?) end }msx;
print "$rule\n";
0 голосов
/ 30 июня 2018

Помимо проблемы с назначением списка скаляру, на которую ikegami указал, шаблон регулярных выражений может использовать некоторые исправления.

Повторитель * в регулярных выражениях является жадным. Он поглощает столько персонажей, сколько может, до тех пор, пока он совпадает. Вы должны позволить другому ретранслятору выполнять смазывание спереди, чтобы его оставалось ровно столько, сколько требуется для репитера, которому вы действительно хотите соответствовать.

my ($rule) = $line =~ /.*\/(.*):/;

Кроме того, в этом случае вы можете просто использовать класс исключения вместо сопоставления с любыми символами.

my ($rule) = $line =~ /\/([^\/]*):/;

Оба вышеперечисленных получат $rule, присвоенные 'VLG6.3'.

0 голосов
/ 30 июня 2018

Вас интересует непустая строка, соответствующая следующим условиям:

  • Ему предшествует /.
  • За ним следует двоеточие.
  • Он не содержит ни /, ни двоеточия.

Итак, интуитивное регулярное выражение без какой-либо группы захвата выглядит так: (?<=\/)[^\/:]+(?=:) (позитивный взгляд, фактическое содержание и позитивный взгляд).

Используя такое регулярное выражение, вы можете:

  • Используйте результат =~ operator only , чтобы проверить, что-то было соответствует.
  • Вывести соответствующий текст из переменной $&.

И пример сценария может выглядеть следующим образом:

use strict;
use warnings;

my $line = 'default_checks/my_checks/VLG6.3: Unsupported system function call';
print "Source: $line\n";
if ($line =~ /(?<=\/)[^\/:]+(?=:)/) {
    print "Rule: $&\n";
} else {
    print "No match.\n";
}
0 голосов
/ 30 июня 2018

Причина, по которой вы получаете 1, заключается в том, что вы оцениваете совпадение в скалярном контексте. Чтобы совпадение возвратило перехваты, оно должно быть оценено в контексте списка.

Вам необходимо оценить соответствие в контексте списка, оценив =~ в контексте списка. В отличие от используемого вами скалярного оператора присваивания, оператор присваивания списка оценивает свои операнды в контексте списка. Вы можете использовать оператор назначения списка, заменив my $rule на my ($rule).

my ($rule) = $line =~ /\/(.*)\:/;

См. Почему в скаляре есть скобки при назначении возвращаемого значения соответствия регулярному выражению в этом фрагменте Perl? .


Кроме того, оператор матча получит больше, чем нужно. Вы можете решить эту проблему, заменив

/\/(.*)\:/

с

/\/([^\/]*)\:/

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

m{/([^/]*):}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...