什么是正则表达式?

时间:2009-07-06 04:20:26

标签: regex parsing

我知道这个问题似乎愚蠢,但事实并非如此。我的意思是完全。我对解析问题有一个公平的理解。我知道BNF / EBNF,我在我的一个大学课程中编写语法来解析简单的无语境语言。我以前从未见过正则表达式!我记得的唯一一件事就是无上下文语法可以做所有正则表达式可以做的事情。

此外,通常的编码解析字符串是否有用?一个简单的例子会有所帮助。

3 个答案:

答案 0 :(得分:35)

正则表达式首先出现在数学和自动机理论中。正则表达式只是定义regular language的东西。如果不过多考虑“常规”的含义,可以这样想一种语言:

  1. 语言由字符串组成。例如,英语是一种语言,它由字符串组成。
  2. 这些字符串由符号组成 - 称为字母表。所以字符串只是字母表中符号的串联。
  3. 所以你可以有一个字符串(记住,只是一个符号串联),它不是给定语言的一部分。或者它可以是语言。

    因此,假设您有一个由2个符号组成的字母:“0”和“1”。并且假设您想要使用该字母表中的符号创建语言。您可以创建以下规则:“为了使字符串符合我的语言,它必须只包含0和1。”

    因此这些字符串使用您的语言:

    • 0
    • 1
    • 01
    • 11001101
    • ...等

    这些不是您的语言:

    • 2
    • 桃子
    • 00101105

    这是一种非常简单的语言。怎么样:“在我的语言中,每个字符串[类似于英语中有效的'单词']必须为0,然后可以跟随任意数字的0或1”

    这些语言为:

    • 0111111
    • 0000000
    • 0101010110001

    这些不是:

    • 1
    • 10000
    • 1010
    • 2000000

    而不是使用单词定义语言 - 而且这些语言可能变得非常复杂(“1后跟2 0后跟1和0的任意组合结束1”),我们提出了这种语法称为“常规”表达“定义语言。

    第一语言应该是:

    (0|1)*

    (0或1,无限重复)

    下一个:0(0|1)*

    (0,后跟任意数字的0和1)。

    让我们现在想一下编程。当你创建一个正则表达式时,你会说“看看这个文本。返回给我符合 this 模式的字符串。”这实际上是在说“我已经定义了一种语言。请在本文档中使用我的语言返回所有字符串。”

    因此,当您创建“正则表达式”时,您实际上是在定义一种常规语言,这是一种数学概念。 (实际上,perl-like regex定义了“非常规”语言,但这是一个单独的问题。)

    通过学习正则表达式的语法,您正在学习如何创建语言的细节,以便稍后您可以看到给定的字符串是否在语言中。因此,通常,人们会说正则表达式用于模式匹配 - 这基本上就是您在查看模式时所做的事情,并查看它是否“匹配”您的语言规则。

    (这很长。它完全回答了你的问题吗?)

答案 1 :(得分:14)

正则表达式是模式匹配的专用语言。它们在许多文本编辑器和编程语言中用于字符串匹配。

你也可以使用正则表达式做更复杂的事情。关于这个主题有一本很棒的O'Reilly书,网上有很多例子。

正则表达式无法解决的问题是正确的解析,因为正则表达式不是编码语法的足够语言。它们专门用于模式匹配,如果您尝试使用它们来解析XML之类的东西,那么您可能会遇到问题。更具体地说,您无法使用正则表达式解析任意嵌套的递归结构。正则表达式无法解决的问题的一个简单示例是一组嵌套大括号,就像您在C中找到的那样:

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

你可以让正则表达式解决这个问题,但随着大括号数量的增加,这个内存需求会随之增大。如果您对更多细节感兴趣,请阅读其他StackOverflow问题,了解为什么这样的构造很难用正则表达式解析:

Can regular expressions be used to match nested patterns?

不同的语言以不同的方式实现正则表达式,但Perl实现非常流行。与Perl兼容的正则表达式系列称为PCRE,或 P erl- C ompatible R egular E Xpressions的。这是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+)/ ) {

阅读方法是:

  • 在条件内,字符串与/'s之间的正则表达式匹配。
  • \ d字符转换为数字0-9。
  • +表示“一次或多次。”
  • parens()表示捕获此匹配,并将其放入特殊变量中。因为这是第一场比赛,所以投入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

希望这足以让你入门!

答案 2 :(得分:2)

其他人已经涵盖了正则表达式是什么,以及它可以用于什么,所以我不会重复以前的答案。但是,如果您有兴趣了解正则表达式语法(即如何构造正则表达式),请查看regular-expression.info上的Tutorial部分;它可能是互联网上最深入的正则表达式语法资源。