Python 用户输入正则表达式,如何正确输入?

Python user input as regular expression, how to do it correctly?

我正在使用 Python 3. 在我的应用程序中,用户可以直接输入正则表达式字符串,应用程序将使用它来匹配一些字符串。例如,用户可以键入 \t+。但是我无法使其工作,因为我无法将其正确转换为正确的正则表达式。我试过了,下面是我的代码。

>>> import re
>>> re.compile(re.escape("\t+")).findall("  ")
[]

然而,当我将正则表达式字符串更改为 \t 时,它将起作用。

>>> re.compile(re.escape("\t")).findall("   ")
['\t']

注意 findall 的参数是制表符。我不知道为什么它在 Whosebug 中似乎没有正确显示。

任何人都可以指出正确的方向来解决这个问题吗?谢谢。

re.escape("\t+")的结果是'\\t\+'。请注意,+ 号用反斜杠转义,不再是特殊字符。不代表"one or more tabs."

来自外部源的文字 \t+ 与文字字符串 "\t+" 不同。 print("\t+") 输出什么? print(r"\t+") 呢?后者相当于接受该文字字符串作为输入以用作正则表达式。前者不是。但是,对于这种特定情况,区别并不重要,因为文字制表符的行为应与正则表达式中的 \t 完全相同。思考 Ipython 会话中的以下示例:

In [24]: re.compile('\t+').findall('^I')
Out[24]: ['\t']

In [25]: re.compile('\t+').findall("\t")
Out[25]: ['\t']

In [26]: re.compile(r'\t+').findall('^I')
Out[26]: ['\t']

In [27]: re.compile(r'\t+').findall("\t")
Out[27]: ['\t']

In [28]: re.compile(r'\t+').findall(r"\t")
Out[28]: []

我只能总结你的第一个例子,那个没有产生预期输出的例子,在引用的字符串中没有文字制表符。

此外,re.escape() 不适合这种情况。其目的是确保来自不受信任来源的字符串按字面意思而不是正则表达式处理,以便它可以安全地用作要匹配的文字字符串。

编译用户输入

我假设用户输入是一个字符串,无论它来自您的系统:

user_input = input("Input regex:")  # check console, it is expecting your input
print("User typed: '{}'. Input type: {}.".format(user_input, type(user_input)))

这意味着您需要将其转换为正则表达式,这就是 re.compile 的用途。如果您使用 re.compile 并且没有提供要转换为正则表达式的有效 str,它将 抛出错误

因此,您可以创建一个函数来检查输入是否有效。你使用了re.escape,所以我在函数中添加了一个标志来决定是否使用re.escape

def is_valid_regex(regex_from_user: str, escape: bool) -> bool:
    try:
        if escape: re.compile(re.escape(regex_from_user))
        else: re.compile(regex_from_user)
        is_valid = True
    except re.error:
        is_valid = False
    return is_valid

print("If you don't use re.escape, the input is valid: {}.".format(is_valid_regex(user_input, escape=False)))
print("If you do use re.escape, the input is valid: {}.".format(is_valid_regex(user_input, escape=True)))

如果您的用户输入是:\t+,您将得到:

>> If you don't use re.escape, the input is valid: True.
>> If you do use re.escape, the input is valid: True.

但是,如果您的用户输入是:[\t+,您将得到:

>> If you don't use re.escape, the input is valid: False.
>> If you do use re.escape, the input is valid: True.

请注意,它确实是一个无效的正则表达式,但是,通过使用 re.escape 您的正则表达式变得有效。这是因为 re.escape 转义 所有特殊字符,将它们视为文字字符。因此,在您有 \t+ 的情况下,如果您使用 re.escape,您将查找一系列字符:\t+ 而不是tab character.

正在检查您的查找字符串

取你要查看的字符串。 例如,这里是一个字符串,其中引号之间的字符应该是一个制表符:

string_to_look_in = 'This is a string with a "  " tab character.'

您可以使用 repr 函数手动检查选项卡。

print(string_to_look_in)
print(repr(string_to_look_in))
>> This is a string with a "    " tab character.
>> 'This is a string with a "\t" tab character.'

请注意,使用 repr 会显示制表符的 \t 表示形式。

测试脚本

这里有一个脚本供您尝试所有这些事情:

import re

string_to_look_in = 'This is a string with a "  " tab character.'
print("String to look into:", string_to_look_in)
print("String to look into:", repr(string_to_look_in), "\n")

user_input = input("Input regex:")  # check console, it is expecting your input

print("\nUser typed: '{}'. Input type: {}.".format(user_input, type(user_input)))


def is_valid_regex(regex_from_user: str, escape: bool) -> bool:
    try:
        if escape: re.compile(re.escape(regex_from_user))
        else: re.compile(regex_from_user)
        is_valid = True
    except re.error:
        is_valid = False
    return is_valid

print("\nIf you don't use re.escape, the input is valid: {}.".format(is_valid_regex(user_input, escape=False)))
print("If you do use re.escape, the input is valid: {}.".format(is_valid_regex(user_input, escape=True)))

if is_valid_regex(user_input, escape=False):
    regex = re.compile(user_input)
    print("\nRegex compiled as '{}' with type {}.".format(repr(regex), type(regex)))

    matches = regex. findall(string_to_look_in)
    print('Mathces found:', matches)

else:
    print('\nThe regex was not valid, so no matches.')