Вопрос по regex, parsing – что такое регулярное выражение?

13

Я знаю этот вопросseems глупо, но это не так. Я имею ввиду что этоexactly, У меня есть четкое понимание проблемы синтаксического анализа. Я знаю BNF / EBNF, я написал грамматику для анализа простых контекстно-свободных языков на одном из моих курсов в колледже. Я просто никогда не встречал регулярных выражений раньше! Единственное, что я помню об этом, это то, что грамматика без контекста может делатьall что может сделать регулярное выражение.

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

-1 Этот очень общий вопрос имеет очень хороший общий ответ в Википедии, с которым следует ознакомитьсяbefore спрашивая. jens
Насколько я помню, одна из заявленных целей StackOverflow состояла в том, чтобы стать чем-то вроде программной википедии, а также в разделе часто задаваемых вопросов, в котором упоминается "Ни один вопрос не является слишком тривиальным или слишком" новичком ". Так что я действительно не понимаю, почему вы отказались от этого. RCIX
@bzlm Как этоnot подотчетны? Mateen Ulhaq
@RCIX Насколько я помню, одной из заявленных целей для StackOverflow было спроситьanswerable вопросы. ;) bzlm
этот вопрос как золотой рудник IAdapter

Ваш Ответ

3   ответа
14

образцом. Они используются во многих текстовых редакторах и языках программирования для сопоставления строк.

Вы можете делать много более сложных вещей с помощью регулярных выражений. По этому вопросу есть отличная книга О'Рейли и многочисленные примеры в Интернете.

То, что вы не можете сделать с регулярными выражениями, - это правильный синтаксический анализ, потому что регулярные выражения не являются достаточным языком для кодирования грамматики. Они специализируются на сопоставлении с образцом, и если вы попытаетесь использовать их для анализа чего-то вроде XML, у вас, вероятно, возникнут проблемы в будущем. Более конкретно, вы не можете анализировать произвольно вложенные рекурсивные структуры с использованием регулярных выражений. Простой пример проблемы, которую регулярное выражение не может решить хорошо, - это набор вложенных фигурных скобок, как вы могли бы найти в C:

int main() {    
    void func() {
    }   
}

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

Можно ли использовать регулярные выражения для сопоставления с вложенными шаблонами?

Различные языки реализуют регулярные выражения по-разному, но реализация Perl очень популярна. Семейство регулярных выражений, совместимых с Perl, называется PCRE, илиPerl-CompatibleRРегулярнаяEXpressions. Вот пример регулярного выражения в Perl, которое может соответствовать целым числам:

#!/usr/bin/perl

use strict;
use warnings;

match_string( "one-two" );
match_string( "1-2" );

sub match_string {
   my $string = shift;
   if ( $string =~ /(\d+)/ ) {
      print "$string matches!\n";
      print "matched: ", $1, "\n";
   } else {
      print "$string doesn't match!\n";
   }
}  

$ perl test.pl 
one-two doesn't match!
1-2 matches!
matched: 1

В этом примере регулярное выражение соответствует одному или нескольким примерам цифры. Вот строка:

   if ( $string =~ /(\d+)/ ) {

Способ прочитать это:

inside the conditional, the string is being matched against the regular expression between /'s. the \d character translates to a digit, 0-9. the + means "one or more times." the parens () mean capture this match, and put it into a special variable. Because this is the first match, it's put into $1.

В некоторых языках (таких как Perl) вы также можете использовать регулярные выражения для выполнения подстановок, например:

substitute_string( "one-two" );
substitute_string( "1-2" );

sub substitute_string {
   my $string = shift;
   print "before: ",  $string, "\n";
   $string =~ s/1/one/g;
   $string =~ s/2/two/g;
   print "after: ",  $string, "\n";
}

$ perl test.pl 
before: one-two
after: one-two
before: 1-2
after: one-two

Надеюсь, этого достаточно, чтобы вы начали!

Perl6 Grammar Engine может на самом деле анализировать любые произвольно вложенные рекурсивные структуры. Вы также можете сделать это с новыми функциямиPerl5.10это просто не так элегантно.
Хорошо объяснил. Пожалуйста, если вы доработаете ответ более подробно и дадите представление о том, что регулярные выражения не могут сделать, а грамматика без контекста может. AraK
2

что такое регулярное выражение и для чего его можно использовать, поэтому я не буду перефразировать предыдущие ответы. Однако, если вы заинтересованы в изучении синтаксиса регулярных выражений (т.е. как создать регулярное выражение), ознакомьтесь сРуководство раздел на регулярном-выражении.info; это, вероятно, самый глубокий ресурс синтаксиса регулярных выражений в Интернете.

35

. Регулярное выражение - это просто то, что определяетобычный язык, Не вдаваясь слишком в то, что «регулярно» значит, думать о языке так:

A language is made up of strings. English is a language, for example, and its made of strings. Those strings are made of symbols - called an alphabet. So a string is just a concatenation of symbols from the alphabet.

Таким образом, вы можете иметь строку (которая, помните, просто конкатенация символов), которая не является частью данного языка. Или это может быть на языке.

Допустим, у вас есть алфавит, состоящий из 2 символов: & quot; 0 & quot; и "1". И скажем, вы хотите создать язык, используя символы в этом алфавите. Вы можете создать следующее правило: "Чтобы строка была на моем языке, в ней должно быть только 0" и 1 ". & Quot;

Итак, эти строки на вашем языке:

0 1 01 11001101 ...etc

Это не будет на вашем языке:

2 peaches 00101105

Это довольно простой язык. Как на счет этого: «На моем языке каждая строка [аналогична действительному» слову ». на английском языке] должен быть с 0, а затем может следовать любое количество 0 'или 1' s & quot;

Это на языке:

0111111 0000000 0101010110001

Это не:

1 10000 1010 2000000

Что ж, вместо того, чтобы определять язык с помощью слов - и эти языки могут стать очень сложными («1, за которым следуют 2 0», а затем любая комбинация 1 »и« 0 », заканчивающаяся 1»), мы придумали это синтаксис под названием "регулярные выражения" определить язык.

Первый язык был бы:

(0|1)*

(0 или 1, повторяется бесконечно)

Следующий:0(0|1)*

(0, за которым следует любое число 0 и 1).

Итак, давайте подумаем о программировании сейчас. Когда вы создаете регулярное выражение, вы говорите "Посмотрите на этот текст". Верни мне строки, которые соответствуютthis . Шаблон & Quot; Что на самом деле говорит: «Я определил язык. Верните мне все строки в этом документе на моем языке. & Quot;

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

Изучая синтаксис регулярных выражений, вы изучаете все тонкости создания языка, чтобы позже вы могли увидеть, находится ли данная строка в «& quot;». язык. Таким образом, обычно люди говорят, что регулярное выражение предназначено для сопоставления с образцом, что в основном и делается, когда вы смотрите на образец и проверяете, соответствует ли он «совпадениям». правила для вашего языка.

(это было долго. Это отвечает на ваш вопрос вообще?)

Имейте в виду, что то, что большинство языков программирования на самом деле реализуют под названием «регулярное выражение» не имеет ничего общего сactual определение «регулярного выражения». По этой причине, например, Ларри Уолл, создатель Perl, переименовал регулярные выражения в «regex». в Perl6, чтобы избежать путаницы:dev.perl.org/perl6/doc/design/apo/A05.html
Хороший ответ - это доходит до сути дела. Интуитивно понятно, что регулярные выражения не имеют памяти. Чистое регулярное выражение не может сопоставить скобки с произвольной глубиной, но язык без контекста может сделать это легко. Однако большинство реализаций регулярных выражений позволяют вам делать больше, чем просто техническое определение.
Прекрасное объяснение. Джордж заполнил последний крошечный пробел :) AraK
Да, это выглядит правильно для меня. Также стоит отметить: синтаксис регулярных выражений Perl отличается от синтаксиса математических регулярных выражений. Но некоторые из них похожи, и концепции очень похожи.
Кстати, ответом на «третий язык является« 100 (0 | 1) * 1 »). ? :) AraK

Похожие вопросы