2010-08-09 140 views
13

我想创建一个Python函数,可以采取简单的英文描述的正则表达式并返回正则表达式给调用者。是否需要更正式表达正则表达式的声明方式? :)

当前我正在考虑YAML格式的描述。 因此,我们可以将描述存储为一个原始字符串变量,将其传递给另一个函数,然后将该函数的输出传递给're'模块。下面是一个比较简单的例子:

# a(b|c)d+e* 
re1 = """ 
- literal: 'a' 
- one_of: 'b,c' 
- one_or_more_of: 'd' 
- zero_or_more_of: 'e' 
""" 
myre = re.compile(getRegex(re1)) 
myre.search(...) 

有谁想到这种事情会更广泛地使用? 你知道现有的软件包可以做到吗? 您看到这种方法的局限性是什么? 有人认为,在代码中使用声明性字符串会使其更易于维护吗?

+0

JSON或XML可能? DTD或XSD也可以很好地描述数据结构。 – codymanix 2010-08-09 11:26:23

+7

所以,不是一个复杂的正则表达式需要一整行,而是需要一整个页面:) – 2010-08-09 11:47:55

+4

知道正则表达式的人对它感到满意,但对其他人来说,它看起来像字母表扔了。这可能是一个问题,但我不确定。毕竟,对于那些编程的人而言,你可以对编程语言说同样的话。 它可能是很好的与对象和函数instad字符串,但我不知道什么是最好的方式来实现的。 +1的创新都一样。 – psicopoo 2010-08-09 11:49:52

回答

2

对于开发人员尝试写正则表达式,很容易去讨论和维护,我想知道这种方法是否会提供re.VERBOSE没有提供的东西。

对于初学者,您的想法可能会有一些吸引力。然而,在你走下这条路之前,你可能会尝试使用捕获组,锚点,预见性断言等来模拟更复杂的正则表达式的声明语法。一个挑战是你可能最终得到一个与正则表达式语言一样难以记住的声明式语法。

您可能还会考虑其他表达方式。例如,我想到的第一个想法是使用简短易记名称的函数表达正则表达式。例如:

from refunc import * 

pattern = Compile(
    'a', 
    Capture(
     Choices('b', 'c'), 
     N_of('d', 1, Infin()), 
     N_of('e', 0, Infin()), 
    ), 
    Look_ahead('foo'), 
) 

但是,当我看到在行动中,它对我来说看起来像一个痛苦。有很多直观的正则表达式的方面 - 例如,+表示“一个或多个”。一种选择是混合方法,允许用户将已经很简单的那些正则表达式的部分与更深奥的位的函数混合在一起。

pattern = Compile(
    'a', 
    Capture(
     '[bc]', 
     'd+', 
     'e*', 
    ), 
    Look_ahead('foo'), 
) 

我想补充说的是,根据我的经验,正则表达式是关于学习思维过程的。熟悉语法是很容易的部分。

6

这实际上与词法分析器/解析器的工作方式非常相似(相同?)。如果你有一个明确的语法,那么你可以编写一个解析器而不会有太多的麻烦。例如,你可以写这样的东西:

<expression> :: == <rule> | <rule> <expression> | <rule> " followed by " <expression> 
<rule>  :: == <val> | <qty> <val> 
<qty>  :: == "literal" | "one" | "one of" | "one or more of" | "zero or more of" 
<val>  :: == "a" | "b" | "c" | "d" | ... | "Z" | 

这远不是一个完美的描述。欲了解更多信息,请看this BNF of the regex language。然后你可以看看lexingparsing的表达式。

如果你这样做,你可能会更接近Natural Language /英文版的正则表达式。


我可以看到像这样的工具很有用,但正如之前所说,主要面向初学者。 这种方法的主要局限性在于需要编写的代码将语言翻译为正则表达式(和/或反之亦然)。另一方面,我认为双向翻译工具实际上会更理想,并且会有更多的用途。能够采用正则表达式并将其转换为英文可能会更有助于发现错误。

当然,拾取正则表达式并不需要太长的时间,因为语法通常是简洁的,大部分的含义都是非常明显的,至少如果你使用|或||作为OR用你的语言,你认为*乘以0-N,+乘以0-N。

虽然有时候我也不会介意键入“找到一个或多个‘A’后面的三个数字或‘B’,那么‘C’”

+0

在回答你的问题时,能够采用正则表达式并将其转换为英文可能会更有助于发现错误。在repl模式下使用Python的re.DEBUG参数。 – Daenyth 2010-08-09 21:21:57

+0

@Daenyth - 我意识到这种模式,虽然我没有理由使用它,但我不能说它比原始正则表达式好得多,除非它是一个非常复杂的正则表达式。 – 2010-08-09 22:11:03

6

请看一看pyparsing。你用RE描述的许多问题都与那些激励我编写该程序包的问题相同。

以下是O'Reilly电子书章节"What's so special about pyparsing?"中pyparsing的一些特定功能。

+1

你打败了我一秒!顺便说一句,感谢您编写pyparsing :) – 2010-08-09 13:06:16

2

你所要求的,也许不完全是,但有一种方法如何写正则表达式更可读的方式(VERBOSE,不久X标志):

rex_name = re.compile(""" 
    [A-Za-z] # first letter 
    [a-z]+  # the rest 
""", re.X) 

rex_name.match('Joe')