为什么在使用 python 正则表达式时多行字符串会导致与单行字符串不同的模式匹配?
Why do multi-line strings lead to different pattern matches from single line strings when using python regex?
我正在尝试创建一个 Discord Bot,它可以读取用户消息并检测他们的消息中何时出现 Amazon link(s) is/are。
如果我使用多行字符串,我会捕获与在单行上使用消息时不同的结果。
这是我使用的代码:
import re
AMAZON_REGEX = re.compile("(http[s]?://[a-zA-Z0-9.-]*(?:amazon|amzn).["
"a-zA-Z]+(?:.+?(?:ref=[^?]+)|.+(?= )|[^?]+))")
def extract_url(message):
foo = AMAZON_REGEX.findall(message)
return foo
user_message = """https://www.amazon.co.uk/dp/B07RLWTXKG blah blah
hello
https://www.amazon.co.uk/dp/B07RLWToop foobar"""
print(extract_url(user_message))
以上代码的结果为:['https://www.amazon.co.uk/dp/B07RLWTXKG blah blah', 'https://www.amazon.co.uk/dp/B07RLWToop']
但是,如果我将 user_message
从多行字符串更改为单行字符串,则会得到以下结果:['https://www.amazon.co.uk/dp/B07RLWTXKG blah blah hello https://www.amazon.co.uk/dp/B07RLWToop']
为什么会这样?另外,如何只捕获 URL 而没有其他用户的消息?
所以您在两个不同的输入源之间得到不同结果的原因是因为您没有对正则表达式中是否存在新行进行任何检查。 This answer 更详细地介绍了可能需要如何修改正则表达式以检测换行符字符串。
但是 - 如果您真正想要的只是获取链接列表而没有其余文本,则最好使用旨在仅捕获 URL 的不同正则表达式字符串。 This post 有几种不同的正则表达式策略来匹配单个 URL.
您使用的正则表达式似乎有问题。
为什么换行会改变输出?
解析 link 后,您的正则表达式似乎捕获了以下单词,由 space 分隔,但换行符阻止正则表达式继续。事实上,在第一种情况下,“blah”和“hello”之间有一个换行符,这是导致在多行情况下无法捕获“hello”的原因。你可能知道,有一个换行符(\n
),有点像a
,*
和其他字符存在。
仅捕获 link
我不太确定亚马逊 link 会采用什么格式,所以很难说它应该是什么样子。但是,您知道 link 不会包含 space,因此当您看到 space 字符时停止匹配是最佳选择。
(http[s]?:\/\/[a-zA-Z0-9.-]*(?:amazon|amzn).[a-zA-Z]+(?:.+?(?:ref=[^?]+)|.+(?= )|[^?]+))
(http[s]?:\/\/[a-zA-Z0-9.-]*(?:amazon|amzn).[a-zA-Z]+(?:.+?(?:ref=[^?]+)|[^ ]+(?= )|[^?]+))
在上面的例子中,我把你的最后一个.
(基本上是“匹配所有字符”)变成了[^ ]
(基本上是“匹配所有除了一个space").这意味着您不会开始匹配单词后 space 之后的单词。
祝 Discord 机器人好运!
我正在尝试创建一个 Discord Bot,它可以读取用户消息并检测他们的消息中何时出现 Amazon link(s) is/are。
如果我使用多行字符串,我会捕获与在单行上使用消息时不同的结果。
这是我使用的代码:
import re
AMAZON_REGEX = re.compile("(http[s]?://[a-zA-Z0-9.-]*(?:amazon|amzn).["
"a-zA-Z]+(?:.+?(?:ref=[^?]+)|.+(?= )|[^?]+))")
def extract_url(message):
foo = AMAZON_REGEX.findall(message)
return foo
user_message = """https://www.amazon.co.uk/dp/B07RLWTXKG blah blah
hello
https://www.amazon.co.uk/dp/B07RLWToop foobar"""
print(extract_url(user_message))
以上代码的结果为:['https://www.amazon.co.uk/dp/B07RLWTXKG blah blah', 'https://www.amazon.co.uk/dp/B07RLWToop']
但是,如果我将 user_message
从多行字符串更改为单行字符串,则会得到以下结果:['https://www.amazon.co.uk/dp/B07RLWTXKG blah blah hello https://www.amazon.co.uk/dp/B07RLWToop']
为什么会这样?另外,如何只捕获 URL 而没有其他用户的消息?
所以您在两个不同的输入源之间得到不同结果的原因是因为您没有对正则表达式中是否存在新行进行任何检查。 This answer 更详细地介绍了可能需要如何修改正则表达式以检测换行符字符串。
但是 - 如果您真正想要的只是获取链接列表而没有其余文本,则最好使用旨在仅捕获 URL 的不同正则表达式字符串。 This post 有几种不同的正则表达式策略来匹配单个 URL.
您使用的正则表达式似乎有问题。
为什么换行会改变输出?
解析 link 后,您的正则表达式似乎捕获了以下单词,由 space 分隔,但换行符阻止正则表达式继续。事实上,在第一种情况下,“blah”和“hello”之间有一个换行符,这是导致在多行情况下无法捕获“hello”的原因。你可能知道,有一个换行符(\n
),有点像a
,*
和其他字符存在。
仅捕获 link
我不太确定亚马逊 link 会采用什么格式,所以很难说它应该是什么样子。但是,您知道 link 不会包含 space,因此当您看到 space 字符时停止匹配是最佳选择。
(http[s]?:\/\/[a-zA-Z0-9.-]*(?:amazon|amzn).[a-zA-Z]+(?:.+?(?:ref=[^?]+)|.+(?= )|[^?]+))
(http[s]?:\/\/[a-zA-Z0-9.-]*(?:amazon|amzn).[a-zA-Z]+(?:.+?(?:ref=[^?]+)|[^ ]+(?= )|[^?]+))
在上面的例子中,我把你的最后一个.
(基本上是“匹配所有字符”)变成了[^ ]
(基本上是“匹配所有除了一个space").这意味着您不会开始匹配单词后 space 之后的单词。
祝 Discord 机器人好运!