什么是正则表达式?

Ara*_*raK 13 regex parsing

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

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

pou*_*def 35

正则表达式首先出现在数学和自动机理论中.正则表达式只是定义常规语言的东西.如果没有过多介绍"常规"的含义,可以这样想一种语言:

  1. 语言由字符串组成.例如,英语是一种语言,它由字符串组成.
  2. 这些字符串由符号组成 - 称为字母表.所以字符串只是字母表中符号的串联.

所以你可以有一个字符串(记住,只是一个符号串联),它不是给定语言的一部分.或者它可能是语言.

因此,假设您有一个由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).

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

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

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

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

  • 好的答案 - 这是事情的核心.直觉上,正则表达式没有内存.纯正则表达式不能将括号与仲裁深度匹配,但是无上下文语言可以轻松地完成.但是,大多数正则表达式实现都很乐意让您做的不仅仅是技术定义. (2认同)

Jam*_*son 14

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

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

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

int main() {    
    void func() {
    }   
}
Run Code Online (Sandbox Code Playgroud)

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

正则表达式可以用于匹配嵌套模式吗?

不同的语言以不同的方式实现正则表达式,但Perl实现非常流行.正则表达式是用Perl兼容的家庭被称为PCRE,或P ERL- C ^ ompatible [R egular ê 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
Run Code Online (Sandbox Code Playgroud)

在此示例中,正则表达式匹配数字的一个或多个示例.这是行:

   if ( $string =~ /(\d+)/ ) {
Run Code Online (Sandbox Code Playgroud)

阅读方式是:

  • 在条件内,字符串与/之间的正则表达式匹配.
  • \ 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
Run Code Online (Sandbox Code Playgroud)

希望这足以让你开始!