Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Регулярные выражения > Не захватывать часть строки


Автор: Pfailed 23.2.2010, 11:53
Возможно ли не захватывать часть строки в захватывающих скобках?
Пример:
Код

$test1 = '+i*5';
$test2 = '-i*8';

$regexp = qr/((?:\+|-)i\*\d)/;
$test1 =~ $regexp or die;
warn $1;
$test2 =~ $regexp or die;
warn $1;


Здесь я хотел бы чтобы захватывающие скобки при захвате пропустили "i*" и в результате получилось
Код

+5
-8


Но как обозначить, что я не хочу захватывать "i*"?
Я понимаю что можно сделать две пары захватывающих скобок и таким образом пропустить ненужные мне символы. Но меня интересует именно такой вариант, где я могу пропустить часть строки в захватывающих скобках.

Автор: Logo 23.2.2010, 15:50
Зачем две пары?
Код

qr/(?:\+|-)i\*(\d)/;
#а лучше
qr/[+-]i\*(\d)/;

Автор: Pfailed 23.2.2010, 15:56
Мне необходимо помимо числа получить и его знак, как указано в первом сообщении.

Автор: Egik2 23.2.2010, 16:08
Подозреваю, что какая бы извращенная фантазия не была у создателей Perlа, в том числе у Ларри Волла.
До такого они не додумались  smile.

Автор: Logo 23.2.2010, 17:23
Аа понял smile. Действительно, это ж надо додуматься.
А чем не устраивают два сохранения?

Автор: Pfailed 23.2.2010, 17:42
На мой взгляд получилось бы эстетичнее чем с двумя захватами.
Интерес тут скорее теоретический, чем практический. Но думаю в будущем может пригодиться.

Автор: Pfailed 23.2.2010, 18:39
http://stackoverflow.com/questions/277547/regular-expression-to-skip-character-in-capture-group, что это сделать невозможно. Что ж, жаль.

Автор: Logo 23.2.2010, 19:48
Цитата

На мой взгляд получилось бы эстетичнее


Вовсе нет. Если  одному захвату на самом деле соответствует два - никакой логики, запутаться на раз-два.

Не встречал задачи где бы это пригодилось.

Впрочем, если очень хочется, есть такой вариант
Код

$test1 = '+i*5';
$test2 = '-i*8';

our $capture;
$regexp = qr/([+-]i\*\d)(?{($capture = $^N)=~ s%i\*%%})/;
$test1 =~ $regexp or die;
warn $capture;
$test2 =~ $regexp or die;
warn $capture;


Автор: Pfailed 23.2.2010, 20:18
Цитата(Logo @  23.2.2010,  19:48 Найти цитируемый пост)
Не встречал задачи где бы это пригодилось.


Просто на днях писал на C++ и заюзал библиотеку регулярных выражений pcre. Вот в голову и пришла мысль, что если бы удалось пропустить ненужные мне символы в строке, то код бы мой слегка упростился, не нужно бы было заводить лишнюю переменную и проверять дополнительное условие:
Код

std::string test = "+i*10";
pcrecpp::RE regexp("([+-]i\\*\\d+)");
int im;

if(regexp.FullMatch(test, &im))
{
     //...
}


А иначе приходится писать так:
Код

std::string test = "+i*10", sign;
pcrecpp::RE regexp("([+-])i\\*(\\d+)");
int im;

if(regexp.FullMatch(test, &sign, &im))
{
   if(sign == "-")
   {
        im = -im;
   }
   //...
}



В Perl конечно эта проблема менее актуальна, так как простые вещи здесь делаются просто.

Код

$regexp = qr/([+-]i\*\d)(?{($capture = $^N)=~ s%i\*%%})/;


Оригинально, но это не решает поставленную задачу.

Автор: vadiml 23.2.2010, 23:08
А почему тогда просто не затирать i* ?

$test1 = '+i*5';
$test1 =~ s/i\*//;
# $test == '+5'

Автор: Pfailed 24.2.2010, 07:19
Да понятно, что есть несколько способов добиться нужного результата. Просто было интересно, а можно ли сделать так как я предложил в первом сообщении.

Автор: Logo 25.2.2010, 18:09
Цитата

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


На C++ сталкиваться с регспами не приходилось. На Perl же просто делается конкатенация, $1.$2, да и на других высокоуровневых языках так же.

Цитата

Оригинально, но это не решает поставленную задачу. 

Почему же? - разве что захват теперь называется не $1, а $capture;  Но кроме Perl ни где работать не будет.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)