5

我认为有一些漂亮的 Pythonic 方法可以做到这一点,但我还没有完全弄清楚。基本上我正在寻找创建一个测试模块,并希望用户能够以一种简单的方式来定义要从中提取的字符集。我可以潜在地连接与字符串相关的各种字符集的列表,但这让我觉得这是一个非常不干净的解决方案。有没有办法获得正则表达式所代表的字符集?

例子:

def foo(regex_set):
    re.something(re.compile(regex_set))

foo("[a-z]")
>>> abcdefghijklmnopqrstuvwxyz

编译当然是可选的,但在我看来,这就是这个函数的样子。

4

4 回答 4

9

Pyparsing的作者 Paul McGuire编写了一个逆正则表达式解析器,您可以使用它执行以下操作:

import invRegex
print(''.join(invRegex.invert('[a-z]')))
# abcdefghijklmnopqrstuvwxyz

如果您不想安装 Pyparsing,还有一个正则表达式逆变器,它仅使用您可以编写的标准库中的模块:

import inverse_regex
print(''.join(inverse_regex.ipermute('[a-z]')))
# abcdefghijklmnopqrstuvwxyz

注意:两个模块都不能反转所有正则表达式模式。


两个模块之间存在差异:

import invRegex
import inverse_regex
print(repr(''.join(invRegex.invert('.'))))
print(repr(''.join(inverse_regex.ipermute('.'))))

产量

'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'

这是另一个区别,这次 pyparsing 枚举了更大的匹配集:

x = list(invRegex.invert('[a-z][0-9]?.'))
y = list(inverse_regex.ipermute('[a-z][0-9]?.'))
print(len(x))
# 26884
print(len(y))
# 1100

于 2013-07-08T19:45:44.977 回答
2

这里不需要正则表达式。如果你想让用户选择一个字符集,让他们只选择字符。正如我在评论中所说,只需列出所有字符并在它们旁边放置复选框就足够了。如果您想要更紧凑或看起来更酷的东西,您可以执行以下操作之一:

显示字母选择的一种方式。 (绿色 = 选中) 显示字母选择的另一种方式。 (没有 x = 选中 显示字母选择的另一种方式。 (黑色背景 = 选中)

当然,如果你真的使用它,你想出的无疑会比这些看起来更好(而且它们实际上也会包含所有字母,而不仅仅是“A”)。

如果需要,您可以包含一个按钮来反转选择、全选、清除选择、保存选择或您需要执行的任何其他操作。

于 2013-07-08T20:15:25.307 回答
1

如果它只是简单的范围,您可以手动解析它

def range_parse(rng):
    min,max = rng.split("-")
    return "".join(chr(i) for i in range(ord(min),ord(max)+1))

print range_parse("a-z")+range_parse('A-Z')

但它的粗...

于 2013-07-08T19:39:46.790 回答
0

我想到的另一个简化问题的解决方案:

将您自己的[]作为提示的一部分放在行上,并在输入中禁止这些字符。在您扫描输入并验证它不包含任何匹配的内容[\[\]]后,您可以在字符串前面[添加和附加],并像正则表达式一样使用它来处理所有需要的字符("abcdefghijklmnopqrstuvwxyz"例如,fort)。

于 2013-07-11T11:34:08.137 回答