2011-01-27 2 views
14

Глядя на некоторые из вопросов регулярного выражения, которые обычно задаются на SO, мне кажется, что существует ряд областей, где традиционный синтаксис regex не соответствует тем задачам, которые люди ищут в настоящее время. Например:Преемник регулярного выражения?

  • Я хочу сопоставить число от 1 до 31, как это сделать?

Обычный ответ не используется для этого регулярного выражения, используйте обычные условные сравнения. Это нормально, если у вас есть только номер сам по себе, но не настолько велика, когда вы хотите совместить число как часть более длинной строки. Почему мы не можем написать что-то вроде \d{1~31} и либо изменить регулярное выражение, чтобы выполнить какую-либо форму подсчета, либо заставить двигатель регулярного выражения перевести его в [1-9]|[12]\d|3[01]?

  • Как совместить четное/нечетное число вхождений определенной строки?

Это приводит к очень грязным регулярным выражениям, было бы здорово, чтобы иметь возможность просто сделать (mytext){Odd}.

  • Как обработать XML с регулярным выражением?

We all know, что это плохая идея, но это и подобные задачи было бы легче, если оператор [^ ] не ограничивается только один символ. Было бы хорошо, чтобы быть в состоянии сделать <name>(.*)[^(</name>)]

  • Как проверить электронную почту с регулярным выражением?

Очень часто делается и все же очень сложно сделать правильно с регулярным выражением. Это спасло бы всех, кто должен был изобрести колесо, если вместо этого можно использовать синтаксис, например {IsEmail}.

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

Является синтаксисом 'regex 2.0', желательно, технически возможным, и есть ли кто-нибудь, работающий над чем-то подобным?

+6

Регулярные выражения являются ** наименьший общий знаменатель ** текста соответствия, и они хороши в этом. Что-нибудь более конкретное будет лучше обрабатываться DSL, чем инструмент общего назначения, который является Regexes. Да, было бы неплохо добавить кухонную раковину в Regexes, но они уже достаточно сложны. Соблазн голосовать за * субъективную и аргументативную *. – deceze

+5

Это называется лексером и парсером. В сети множество генераторов. Они были вокруг, вероятно, до тех пор, как Regex. – leppie

+1

большой вопрос, miket2e. о «да, точно, что с этим связано?» вопросов. к сожалению, у меня нет ответа, но мне интересно узнать ваши результаты. – kostja

ответ

16

Я считаю, что Ларри Уолл покрыл это Perl 6 regexes. Основная идея - заменить простые регулярные выражения более полезными правилами грамматики. Их легче читать, и легче вводить код для таких вещей, как убедиться, что у вас есть несколько совпадений. Кроме того, вы можете назвать такие правила, как IsEmail. Я не могу перечислить все подробности здесь, но достаточно сказать, это похоже на то, что вы предлагаете.

Вот некоторые примеры из http://dev.perl.org/perl6/doc/design/exe/E05.html:

Matching IP адрес:

token quad { (\d**1..3) <?{ $1 < 256 }> } 
$str ~~ m/ <quad> <dot> <quad> <dot> <quad> <dot> <quad> /; 

Matching вложенными скобками:

$str =~ m/ \( [ <-[()]> + : | <self> ]* \) /; 

Аннотированный:

$str =~ m/ <'('>    # Match a literal '(' 
       [     # Start a non-capturing group 
        <-[()]> +  # Match a non-paren (repeatedly) 
        :    # ...and never backtrack that match 
       |     # Or 
        <self>   # Recursively match entire pattern 
       ]*     # Close group and match repeatedly 
       <')'>    # Match a literal ')' 
      /; 
+0

Просто писал о том же :-) – kriss

+0

Очень интересно, спасибо. – mikel

+0

Если вы хотите грамматики, то у Prolog всегда есть встроенные DCG (определенные грамматические выражения), и они строго более мощные, чем контекстно-зависимые языки (они должны быть чем-то вроде индексированных грамматик, afaik)! Просто это решение, ориентированное на язык, не является общим решением. –

5

Возможно, это уже есть и с давних времен. Это называется «грамматики». Вы когда-нибудь слышали о yacc и lex? Теперь нужно что-то простое. Как это ни странно, большая сила регулярного выражения заключается в том, что их очень просто написать на месте.

Я верю в некоторые (но большие) специализированные области, в которых уже есть что нужно. Я думаю о синтаксисе XPath.

Существует ли более крупная (не ограниченная XML, но все еще простая) альтернатива, которая может охватывать все случаи? Возможно, вам стоит взглянуть на perl 6 grammars.

17

Не вините инструмент, обвините пользователя.

Регулярные выражения были созданы для сопоставления шаблонов в строках. Вот и все..

Это не было сделано для:

  • проверки Integer
  • язык разметки разборе
  • Очень сложная проверка (т.е. .: RFC 2822)
  • Точное сравнение строк
  • коррекции орфографии
  • Векторный расчет
  • Генетическое декодирование
  • Чудо делает
  • младенца экономию
  • Финансы введения
  • субатомной перегородка
  • активации
  • Деформации ядра зацепления
  • Времени путешествия
  • Головной боли индуцирующего
    Никогда-ум Flux конденсатора это последний. Кажется, что регулярные выражения очень хорошо адаптированы к выполнению этой последней задачи, когда они используются там, где они не должны.

Следует ли переделать отвертку, потому что она не умеет гвоздь? NO, используйте молоток.

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

  • Я хочу, чтобы соответствовать число от 1 до 31, как я могу это сделать?
    Используйте свои языковые конструкции, чтобы попытаться преобразовать строку в целое число и выполнить соответствующие сравнения.

  • Как совместить четное/нечетное число вхождений определенной строки?
    Регулярные выражения не являются синтаксическим анализатором строк. Вы можете, однако, извлечь соответствующую часть с регулярным выражением, если вам нужно только разобрать подраздел исходной строки.

  • Как обработать XML с регулярным выражением?
    У вас нет. Используйте XML или HTML-парсер в зависимости от ваших потребностей. Кроме того, синтаксический анализатор XML не может выполнять работу с парсером HTML (если у вас нет полностью сформированного документа XHTML), и обратное также верно.

  • Как проверить письмо с регулярным выражением?
    Вы либо используете this large abomination, либо вы делаете это правильно with a parser.

+1

Я вижу вашу точку зрения, но я не предлагаю, чтобы они были полностью переработаны. Просто кажется, что есть возможность улучшить их несколькими способами, чтобы соответствовать тем вещам, которые люди сейчас пытаются с ними делать. – mikel

+0

@ miket2e: Проблема в том, что его нельзя использовать, чтобы делать эти вещи в первую очередь. Это никогда не было правильным инструментом, и есть множество инструментов, которые построены именно для выполнения этих задач. Регулярные выражения сейчас очень хороши в том, что они должны делать. ** Вилка - это вилка. Ложка - ложка. Вы можете поверить, что хотите получить spork, но это не так полезно, как кажется. ** Я окончательно не хочу, чтобы регулярные выражения стали spork. –

+0

Он не говорит: «Поверните регулярные выражения в spork»; он говорит: «Давайте создадим новый инструмент для замены регулярных выражений, которые могут делать регулярные выражения, которые не подходят». – Gabe

2

Нет. Мы должны оставлять регулярные выражения как есть. Они уже слишком сложны. Когда вы в последний раз думали, что прибили его, т. Е. Получили полный расширенный синтаксис регулярного выражения (выберите свой вкус), загруженный в вашу сквошную память?

Теория позади регулярных выражений - это приятно и просто. Но тогда мы хотели, чтобы это и было с ним. Инструмент полезен, но не подходит для нерегулярного сопоставления. Все в порядке!

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

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

5

Все это возможно на Perl.

Чтобы соответствовать 1..31 с регулярными выражениями шаблона:

/([0-9]+) (?(?{ $^N < 1 && $^N > 31 })(*FAIL)) /x 

Чтобы создать что-то вроде [1-9]|[12]\d|3[01]:

use Regexp::Assemble qw(); 
my $ra = Regexp::Assemble->new(); 
$ra->add($_) for (1..31); 
my $re = $ra->re;     # qr/(?:[456789]|3[01]?|1\d?|2\d?)/ 

Perl 5.10+ использует пытается оптимизировать чередований, так что следующий должен быть достаточным:

my $re = join '|', 1..31; 
$re = qr/$re/; 

Чтобы соответствовать четное число вхождений:

/ (?: pat{2})* /x 

Для того, чтобы соответствовать нечетное число вхождений:

/ pat (?: pat{2})* /x 

Образец neg ческие матч:

/<name> (.*?) </name>/x # Non-greedy matching 

/<name> ((?: (?!</name>).)*) </name>/x 

Чтобы получить шаблон сопоставления адресов электронной почты:

use Regexp::Common qw(Email::Address); 
/$RE{Email}{Address}/