Как я могу сопоставить все, что находится после последнего появления некоторого символа в регулярном выражении perl? - PullRequest
14 голосов
/ 09 августа 2010

Например, вернуть часть строки, которая находится после последней x в axxxghdfx445 (должна возвращаться 445).

Ответы [ 7 ]

17 голосов
/ 09 августа 2010
my($substr) = $string =~ /.*x(.*)/;

От perldoc perlre:

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

Именно поэтому .*x будет соответствовать до последнего вхождения x.

10 голосов
/ 09 августа 2010

Самый простой способ - использовать /([^x]*)$/

5 голосов
/ 09 августа 2010

первый ответ хороший, но когда речь идет о «чем-то, что не содержит» ... мне нравится использовать регулярное выражение, которое «соответствует» ему

my($substr) = $string =~ /.*x([^x]*)$/;

очень полезно в некоторых случаях

3 голосов
/ 09 августа 2010

Я удивлен, что никто не упомянул специальную переменную, которая делает это, $': "$'" возвращает все после соответствующей строки. ( perldoc perlre )

my $str = 'axxxghdfx445';
$str =~ /x/;

# $' contains '445';
print $';

Тем не менее, есть стоимость (выделено мое):

ВНИМАНИЕ: Как только Perl увидит, что вам нужен один из $ &, "$ ", or "$'" anywhere in the program, it has to provide them for every pattern match. This may substantially slow your program. Perl uses the same mechanism to produce $1, $2, etc, so you also pay a price for each pattern that contains capturing parentheses. (To avoid this cost while retaining the grouping behaviour, use the extended regular expression "(?: ... )" instead.) But if you never use $&, "$" или "$ '", тогда шаблоны без захват скобок не будет оштрафован. Так что избегайте $ &, "$ '" и «$` », если вы можете, но если вы не можете (и некоторые алгоритмы действительно цените их), как только вы использовали их один раз, используйте их по желанию, потому что Вы уже заплатили цену. По состоянию на 5.005 $ & не так дорого, как два других.

Но подождите, это еще не все! Вы получаете двух операторов по цене одного, действуйте СЕЙЧАС!

В качестве обходного пути для этой проблемы в Perl 5.10.0 вводится «$ {^ PREMATCH}», «$ {^ MATCH}» и «$ {^ POSTMATCH}», которые эквивалентны в $ `, $ & и $ $, за исключением того, что они гарантированно определяется после успешного совпадения, которое было выполнено с "/ p" (сохранить) модификатор. Использование этих переменных не требует штраф за производительность, в отличие от их знаков препинания, однако при компромиссе, который вы должны сообщить Perl, когда хотите их использовать.

my $str = 'axxxghdfx445';
$str =~ /x/p;

# ${^POSTMATCH} contains '445';
print ${^POSTMATCH};

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

3 голосов
/ 09 августа 2010

Еще один способ сделать это.Это не так просто, как одно регулярное выражение, но если вы оптимизируете скорость, этот подход, вероятно, будет быстрее, чем что-либо, использующее регулярные выражения, включая split.

my $s     = 'axxxghdfx445';
my $p     = rindex $s, 'x';
my $match = $p < 0 ? undef : substr($s, $p + 1);
2 голосов
/ 09 августа 2010

Самый простой способ - это не регулярное выражение, а простая функция split () и получение последнего элемента.

$string="axxxghdfx445";
@s = split /x/ , $string;
print $s[-1];
1 голос
/ 09 августа 2010

Регулярное выражение : /([^x]+)$/ #assuming x is not last element of the string.

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