我们说我的脚本中定义了以下正则表达式。我希望将这些评论留给我,因为我很健忘。
RE_TEST = re.compile(r"""[0-9] # 1 Number
[A-Z] # 1 Uppercase Letter
[a-y] # 1 lowercase, but not z
z # gotta have z...
""",
re.VERBOSE)
print(magic_function(RE_TEST)) # returns: "[0-9][A-Z][a-y]z"
Python(3.4+)是否有办法将其转换为简单字符串"[0-9][A-Z][a-y]z"
?
This question ("strip a verbose python regex")似乎与我要求的非常接近,而且是answered。但那是几年前的事情,所以我想知道是否找到了新的(最好是内置的)解决方案。
除了上述内容之外,还有一些解决方法,例如使用隐式字符串连接,然后使用.pattern
属性:
RE_TEST = re.compile(r"[0-9]" # 1 Number
r"[A-Z]" # 1 Uppercase Letter
r"[a-y]" # 1 lowercase, but not z
r"z", # gotta have z...
re.VERBOSE)
print(RE_TEST.pattern) # returns: "[0-9][A-Z][a-y]z"
或者只是单独评论模式而不是编译模式:
# matches pattern "nXxz"
RE_TEST = "[0-9][A-Z][a-y]z"
print(RE_TEST)
但我真的很想保持编译的正则表达式(第一个例子)。也许我正在从某个文件中提取正则表达式字符串,并且该文件已经在使用详细格式。
我问,因为我想建议编辑unittest
模块。
现在,如果使用带注释的编译模式运行assertRegex(string, pattern)
并且断言失败,那么打印输出有点难看(下面是虚拟正则表达式):
Traceback (most recent call last):
File "verify_yaml.py", line 113, in test_verify_mask_names
self.assertRegex(mask, RE_MASK)
AssertionError: Regex didn't match: '(X[1-9]X[0-9]{2}) # comment\n |(XXX[0-9]{2}) # comment\n |(XXXX[0-9E]) # comment\n |(XXXX[O1-9]) # c
omment\n |(XXX[0-9][0-9]) # comment\n |(XXXX[
1-9]) # comment\n ' not found in 'string'
我将通过移除注释和额外的空格或以不同的方式打印它来预测assertRegex
和assertNotRegex
方法在打印之前清理正则表达式。
答案 0 :(得分:3)
以下测试过的脚本包含一个功能,可以很好地将xmode正则表达式字符串转换为非xmode:
pcre_detidy(retext)
# Function pcre_detidy to convert xmode regex string to non-xmode.
# Rev: 20160225_1800
import re
def detidy_cb(m):
if m.group(2): return m.group(2)
if m.group(3): return m.group(3)
return ""
def pcre_detidy(retext):
decomment = re.compile(r"""(?#!py/mx decomment Rev:20160225_1800)
# Discard whitespace, comments and the escapes of escaped spaces and hashes.
( (?: \s+ # Either g1of3 $1: Stuff to discard (3 types). Either ws,
| \#.* # or comments,
| \\(?=[\r\n]|$) # or lone escape at EOL/EOS.
)+ # End one or more from 3 discardables.
) # End $1: Stuff to discard.
| ( [^\[(\s#\\]+ # Or g2of3 $2: Stuff to keep. Either non-[(\s# \\.
| \\[^# Q\r\n] # Or escaped-anything-but: hash, space, Q or EOL.
| \( # Or an open parentheses, optionally
(?:\?\#[^)]*(?:\)|$))? # starting a (?# Comment group).
| \[\^?\]? [^\[\]\\]* # Or Character class. Allow unescaped ] if first char.
(?:\\[^Q][^\[\]\\]*)* # {normal*} Zero or more non-[], non-escaped-Q.
(?: # Begin unrolling loop {((special1|2) normal*)*}.
(?: \[(?::\^?\w+:\])? # Either special1: "[", optional [:POSIX:] char class.
| \\Q [^\\]* # Or special2: \Q..\E literal text. Begin with \Q.
(?:\\(?!E)[^\\]*)* # \Q..\E contents - everything up to \E.
(?:\\E|$) # \Q..\E literal text ends with \E or EOL.
) [^\[\]\\]* # End special: One of 2 alternatives {(special1|2)}.
(?:\\[^Q][^\[\]\\]*)* # More {normal*} Zero or more non-[], non-escaped-Q.
)* (?:\]|\\?$) # End character class with ']' or EOL (or \\EOL).
| \\Q [^\\]* # Or \Q..\E literal text start delimiter.
(?:\\(?!E)[^\\]*)* # \Q..\E contents - everything up to \E.
(?:\\E|$) # \Q..\E literal text ends with \E or EOL.
) # End $2: Stuff to keep.
| \\([# ]) # Or g3of3 $6: Escaped-[hash|space], discard the escape.
""", re.VERBOSE | re.MULTILINE)
return re.sub(decomment, detidy_cb, retext)
test_text = r"""
[0-9] # 1 Number
[A-Z] # 1 Uppercase Letter
[a-y] # 1 lowercase, but not z
z # gotta have z...
"""
print(pcre_detidy(test_text))
这个函数是用pcre-8 / pcre2-10 xmode语法编写的正则表达式。
它保留[character classes]
,(?#comment groups)
和\Q...\E
文字文字范围内的空白。
上面的decomment
正则表达式是我即将发布的RegexTidy应用程序中使用的一个变体,它不仅会解决上面显示的正则表达式(这很漂亮)很容易做到,但它也会走另一条路并且 Tidy 一个正则表达式 - 即将它从非xmode正则表达式转换为xmode语法,向嵌套组添加空格缩进以及添加注释(更难)。
P.S。在给出这个答案之前,一般原则是因为它使用的是一个长于几行的正则表达式,请添加一个描述一个未正确处理的示例的注释。干杯!
答案 1 :(得分:1)
通过查看sre_parse
处理此问题的方式,确实没有任何一点可以将详细的正则表达式“转换”为常规正则表达式然后进行解析。相反,你的详细正则表达式被直接提供给解析器,其中VERBOSE
标志的存在使得它忽略字符类外的非转义空格,并且从未转义的#
到行尾(如果是)不在字符类或捕获组(文档中缺少)中。
解析你的详细正则表达式的结果不是"[0-9][A-Z][a-y]z"
。相反它是:
[(IN, [(RANGE, (48, 57))]), (IN, [(RANGE, (65, 90))]), (IN, [(RANGE, (97, 121))]), (LITERAL, 122)]
为了正确地将您的详细正则表达式转换为"[0-9][A-Z][a-y]z"
,您可以自己解析它。您可以使用pyparsing
之类的库来执行此操作。在您的问题中链接的另一个答案使用正则表达式,它通常不会正确复制行为(特别是字符类中的空格和#捕获组/字符类内部。甚至只是处理转义并不像使用好的解析器那样方便。 )