В Perl, сколько групп входит в соответствующее регулярное выражение? - PullRequest
1 голос
/ 11 ноября 2011

Я хотел бы сказать разницу между числом 1 и строкой '1'.

. Причина, по которой я хочу это сделать, заключается в том, что я хочу определить количество вводимых скобок в регулярномвыражение после успешного совпадения.Согласно документу perlop, список (1) возвращается, когда в шаблоне нет групп захвата.Поэтому, если я получу успешное совпадение и список (1), я не смогу определить, нет ли в шаблоне ни одного символа, ни одного, и он соответствует «1».Я могу устранить эту двусмысленность, если есть разница между числом 1 и строкой '1'.

Ответы [ 6 ]

6 голосов
/ 11 ноября 2011

Вы можете определить количество групп захвата в последнем успешном сопоставлении, используя специальный массив @ + . $#+ - количество групп захвата. Если это 0, то не было никаких захватывающих скобок.

2 голосов
/ 11 ноября 2011

Например, побитовые операторы ведут себя по-разному для строк и целых чисел:

~1 = 18446744073709551614

~'1' = Î ('1' = 0x31, ~ '1' = ~ 0x31 = 0xce ='Î')

#!/usr/bin/perl

($b) = ('1' =~ /(1)/);
print isstring($b) ? "string\n" : "int\n";
($b) = ('1' =~ /1/);
print isstring($b) ? "string\n" : "int\n";

sub isstring() {
    return ($_[0] & ~$_[0]);
}

isstring возвращает либо 0 (как результат числовой побитовой операции), который равен false, либо "\ 0" (как результат побитовой операции ввода строк, установите perldoc perlop), который равенистина, так как это непустая строка.

1 голос
/ 12 ноября 2011

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

Вы можете получить счет, посмотрев на результат назначения списка, который возвращает количество элементов в правой части назначения списка:

my $count = my @array = $string =~ m/.../g;

Если вам не нужно сохранять буферы захвата, присвойте пустой список:

my $count = () = $string =~ m/.../g;

Или сделать это в два этапа:

my @array = $string =~ m/.../g;
my $count = @array;

Вы также можете использовать переменные @+ или @-, используя некоторые приемы, которые я показал на первых страницах Освоение Perl . Эти массивы имеют начальную и конечную позиции каждого из буферов захвата. Значения в индексе 0 применяются ко всему шаблону, значения в индексе 1 относятся к $1 и т. Д. Таким образом, последний индекс - это общее количество буферов захвата. См. perlvar .

0 голосов
/ 11 ноября 2011

Проверка на определенность в $ 1 после успешного совпадения. Логика выглядит так:

  • Если список пуст, то совпадение с шаблоном не удалось
  • Иначе, если определено $ 1, список содержит все подстроки catpured
  • В остальном матч прошел успешно, но захватов не было
0 голосов
/ 11 ноября 2011

Ваш вопрос не имеет большого смысла, но, похоже, вы хотите знать разницу между:

$a = "foo"; 
@f = $a =~ /foo/; 

и

$a = "foo1"; 
@f = $a =~ /foo(1)?/; 

Поскольку они оба возвращают одну и ту же вещь, независимо от того, был ли сделан захват.

Ответ таков: не пытайтесь использовать возвращенный массив. Проверьте, не является ли $1 не равным ""

0 голосов
/ 11 ноября 2011

Perl конвертирует между строками и числами автоматически по мере необходимости. Внутри он отслеживает значения отдельно. Вы можете использовать Devel :: Peek, чтобы увидеть это в действии:

use Devel::Peek;
$x = 1;
$y = '1';
Dump($x);
Dump($y);

Вывод:

SV = IV(0x3073f40) at 0x3073f44
  REFCNT = 1
  FLAGS = (IOK,pIOK)
  IV = 1
SV = PV(0x30698cc) at 0x3073484
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x3079bb4 "1"\0
  CUR = 1
  LEN = 4

Обратите внимание, что дамп $x имеет значение для слота IV, в то время как дамп $y не имеет значения в слоте PV. Также обратите внимание, что простое использование значений в другом контексте может вызвать строковое преобразование или нумерацию и заполнение других слотов. например если вы сделали $x . '' или $y + 0 до того, как заглянули в значение, вы получите это:

SV = PVIV(0x2b30b74) at 0x3073f44
  REFCNT = 1
  FLAGS = (IOK,POK,pIOK,pPOK)
  IV = 1
  PV = 0x3079c5c "1"\0
  CUR = 1
  LEN = 4

В этот момент 1 и '1' больше не различимы вообще.

...