我试图为要创建textmate grammar的项目学习正则表达式,正则表达式似乎相对简单,但对我来说真的很难阅读,因此我尝试创建实用程序python module可以生成它们,它可以按预期工作并生成实际起作用的正则表达式,所有这些都以易于理解的名称作为别名。
例如:
struc_enum = OrGroup("struct", "enum")
whitespace = TAB_SPACE.at_least(1)
导致:
(?:struct|enum)
[ \t]+
在这种情况下,使用python别名并没有太多好处,但是我可以这样做:
valid_name = r"\b" + Group(ALPHA, ALPHANUMERIC.repeated())
struc_enum = OrGroup("struct", "enum")
typed_name = (struc_enum + whitespace).optional() + valid_name + whitespace + valid_name.captured()
print(typed_name)
显示的是
(?:(?:(?:struct|enum)[ \t]+)?\b[a-zA-Z][a-zA-Z\d]*[ \t]+(\b[a-zA-Z][a-zA-Z\d]*))
此方法可用于创建小的代码段并将其连接起来以构建更复杂的模式,但是对于每个级别的连接,表达式都会成倍增长,这样我就可以很容易地理解到这一点:
(?:(func)[\s]+([a-zA-Z_]+[a-zA-Z\d_]*)[\s]*\([\s]*(?:[a-zA-Z_]+[a-zA-Z\d_]*(?:[\s]*[a-zA-Z_]+[a-zA-Z\d_]*[*]{,2})?(?:[\s]*,[\s]*[a-zA-Z_]+[a-zA-Z\d_]*(?:[\s]*[a-zA-Z_]+[a-zA-Z\d_]*[*]{,2})?)*[\s]*)?\))
在原子语法中,上面的大正则表达式可以匹配这样的行,但在其他地方似乎不起作用:
func myfunc(asd asd*, asd*, asdasd)
func do_foo01(type arg1, int arg2)
如果有足够的耐心,一个人可能会构建一个等效的表达式,但可能会简短得多,这引发了一个问题。在计算开销方面,大正则表达式是否比等效的短表达式差或更佳?在什么时候我们可以认为正则表达式太大?
答案 0 :(得分:1)
由于您要解决的原始问题是长正则表达式难以阅读,因此您不妨考虑扩展(详细)正则表达式。扩展的正则表达式允许空格和注释,这可以使正则表达式更易于阅读。
对比此正则表达式:
charref = re.compile("&#(0[0-7]+"
"|[0-9]+"
"|x[0-9a-fA-F]+);")
具有相同的正则表达式,并带有注释:
charref = re.compile(r"""
&[#] # Start of a numeric entity reference
(
0[0-7]+ # Octal form
| [0-9]+ # Decimal form
| x[0-9a-fA-F]+ # Hexadecimal form
)
; # Trailing semicolon
""", re.VERBOSE)
答案 1 :(得分:0)
我认为这是个好主意,但是您需要清楚自己正在进行的项目的规模。
我们几乎永远不需要使用正则表达式;我们可以分解每个字符串并使用starts_with
和if
等编写我们自己的解析操作。但是regex语法是一个成熟,强大系统让我们简洁表达某些逻辑。
通常很难阅读正则表达式。有some tools可以提供帮助,但是一个不太简洁的系统来完成我们目前对正则表达式所做的工作的想法是合理的。困难的部分将是复制现有正则表达式系统的宽度,功能和可靠性。
我的猜测是,学习容忍正则表达式的密度将为您提供最好的服务。通过构建易于理解的字符串解析系统,也许我们可能会得到更好的服务,但是您将需要大约20年的时间来完成这项工作。
关于性能:正则表达式已被编译。根据上下文,这可能会带来很大的性能优势。
无论如何,就像任何足够强大的语言一样,指令的长度不足以指示其运行时的复杂性。