Подход, который вы выбираете, зависит от того, чего вы пытаетесь достичь sh и от всего остального, что связано с проблемой. Так как вы ничего не сказали об этом, вот дробовик различных идей. Не все из них могут подходить для того, что вы делаете.
Специальная переменная @-
имеет смещения для начальной позиции групп совпадений. Первый элемент - начало всего совпадения, второй элемент (индекс 1) - начало совпадения $1
и т. Д. Если ваш шаблон - это вся строка, которую вы хотите, тогда вы можете использовать первый элемент в этом массиве:
if( $string =~ /\bv\d+\.\d+\.\d+\b/ ) {
my $position = $-[0];
say "Position is $position";
}
Если у вас есть другие вещи вокруг вашего шаблона, и материал, который вы хотите, находится в первой группе совпадений, Вы можете использовать второй элемент (помните, что группы совпадений нумеруются по порядку открывающих паренов):
if( $string =~ /before (v\d+\.\d+\.\d+) after/ ) {
my $position = $-[1];
say "Position is $position";
}
При изменении вашего паттерна вам может потребоваться обновление с помощью используемого вами элемента.
Там также @+
, который работает так же, но имеет конечную позицию. У меня есть несколько примеров этого в первом издании Мастеринг Perl. Я сохранил это для этой книги, потому что я нахожу, что многие люди запутываются в том, какой элемент соответствует какой части шаблона. Подумайте, вспомните ли вы это позже.
Вы можете использовать index
, чтобы получить позицию соответствующей строки:
if( $string =~ /\b(v\d+\.\d+\.\d+)\b/ ) {
my $matched = $1;
my $position = index( $string, $matched );
say "Position is $position";
}
Используя флаг /p
и переменную ${^PREMATCH}
начиная с Perl v5.10, подсчитайте позиции перед совпавшей частью строки:
use v5.10;
if( $string =~ /\bv\d+\.\d+\.\d+\b/p ) {
my $position = length ${^PREMATCH};
say "Position is $position";
}
Используйте флаг /g
в скалярном контексте и Perl запоминает позицию строки, где закончилось совпадение. Вычтите длину совпадения, чтобы увидеть, где началось совпадение:
if( $string =~ /\b(v\d+\.\d+\.\d+)\b/g ) {
my $matched = $1;
my $position = pos( $string ) - length($1);
say "Position is $position";
}
Если в строке может быть несколько совпадений, вам придется их откорректировать. Один способ использует циклы while
, так как условие по-прежнему является скалярным контекстом:
while( $string =~ /\b(v\d+\.\d+\.\d+)\b/g ) {
my $matched = $1;
my $position = pos( $string ) - length($1);
say "Position is $position";
}