Как я могу определить положение шаблона в строке? - PullRequest
1 голос
/ 24 февраля 2020

Я хочу сопоставить шаблон с этим форматом /vX.X.X/, где X число. Например: /v1.1.1/ и /v1.0.300/. После сопоставления шаблона, как я могу получить позицию в строке, где я нашел шаблон?

Ответы [ 2 ]

7 голосов
/ 24 февраля 2020

@- содержит смещения, в которых были найдены совпадения и захваты.

  • $-[0] - это смещение, с которым сопоставляется шаблон.
  • $-[1] - это смещение, при котором сопоставляется первый захват.
  • $-[2] - это смещение, при котором сопоставляется второй захват.
  • et c.

Таким образом, Вы можете использовать следующее:

if ( $s =~ m{/v\d+\.\d+\.\d+/}a ) {
   say "Matched at position $-[0]";
}
3 голосов
/ 24 февраля 2020

Подход, который вы выбираете, зависит от того, чего вы пытаетесь достичь 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";
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...