LINUX.ORG.RU

Регулярные выражения, конструкция между повторениями, есть такое?

 


0

1

Если я делаю сложное выражение, а потом хочу его множественное повторение с промежуточным символом. Но после последнего элемента, промежуточный символ не нужен.

Как написать такое выражение, что бы то сложное выражение не писать дважды?

Например:

^(?:(?:[2-9][1-4]|1[0-4][1-4])[-+ ])+$
Здесь это последовательность цифр вводимых на правой клавиатуре, и между цифрами может быть как пробел, так и плюс или минус.

Т.е. здесь [-+ ] - это символ между конструкциями. Как сделать, что бы при последнем повторении он не проверялся.
Только между конструкциями (?:[2-9][1-4]|1[0-4][1-4])

Не совсем по теме, но не могу понять что данная конструкция делает вообще; если это BRE, то | не работает; если ERE, то ‘?’ это оператор повторения.

И какая задача, проверить полностью строку на соответствие?

dsdqmhsx
()
Ответ на: комментарий от dsdqmhsx

если это BRE, то | не работает; если ERE, то ‘?’

я его еще не тестил, (?: это не сохраняемая скобка (Non-capturing group). И да, это совсем не по теме вопроса.

Вопрос, как сделать, что бы это (?:[2-9][1-4]|1[0-4][1-4]) не нужно было писать дважды, типа:

^(?:[2-9][1-4]|1[0-4][1-4])(?:[-+ ](?:[2-9][1-4]|1[0-4][1-4]))*$

victor79
() автор топика
Последнее исправление: victor79 (всего исправлений: 3)
Ответ на: комментарий от dsdqmhsx

Похоже, что так работает с ERE:
^(([2-9][1-4]|1[0-4][1-4])([-+ ]|$))+$

Если последний символ не конец строки? То так уже не составить.
Странно, довольно частая ситуация, а удобную фичу для этого не сделали...

victor79
() автор топика

регулярка для 0-255 выглядит так:

[0, 1, 19, 109, 255, 256].map(x =>  x  + ' '  + /^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])$/.test(x))
(6) ['0 true', '1 true', '19 true', '109 true', '255 true', '256 false']
tz4678 ★★
()
Ответ на: комментарий от tz4678

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

tz4678 ★★
()

Если ты какой-то калькулятор делаешь, то там что-то типа такого:

~ 
➜ ipython
Python 3.9.6 (default, Jun 30 2021, 10:22:16) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.27.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: s = '2 + 2'

In [2]: s.split()
Out[2]: ['2', '+', '2']

# А потом выражение нужно представить в обратной польской нотации с учета приоритета операторов
In [3]: ['+', 2, 2]
Out[3]: ['+', 2, 2]

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

Если ты хочешь проверять выражениятипа 2 + 3 - 4, то там все предельно просто: \d+([+-/*]\d+)+, но это слишком примитивно, потому как +3 - это валидное математическое выражение и ((+3)), и (2+3)/-4

tz4678 ★★
()
Ответ на: комментарий от tz4678

Что-то типа такого, если без скобок:

In [4]: num_re = '[-+]?\d+'

In [5]: num_re + '([-+*/]' + num_re + ')+'
Out[5]: '[-+]?\\d+([-+*/][-+]?\\d+)+'

И еще проблелы предварительно вырезать.

tz4678 ★★
()
Ответ на: комментарий от tz4678

Что-то типа такого

Вот и приходится придумывать костыли.

Как-то давным давно, когда у меня было мозгов по меньше/больше, я делал свою реализацию регулярок. Так в их синтаксис как раз я включил такую конструкцию, которая соединяла такие последовательности. Было удобно.

victor79
() автор топика
#!/usr/bin/env perl

use v5.26;

my $s = '123 456 789 123';

say 'MATCHED!' if $s =~ /(\d{3}) (?1) (?1) \g1/;

Вот, браток, смотри чего есть. (?n) - это рекурсивные шаблончики. Т.е. на место этой конструкции, подставится шаблон из первой группы (группа - ограниченная скобками вещь). А \g1 - это взадссылка (backreference). Здесь на место метасимвола подставляется строка, которая совпала в первой группе (именно результат совпадения, а не шаблон). Т.е. «эквивалентно», что было понятней, можно переписать этот регвыр для данной строки как-то так: /\d{3} \d{3} \d{3} 123/

Учите Perl и не болейте, пацаны!

perl5_guy ★★★★★
()
Последнее исправление: perl5_guy (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.