Regex, capture using word boundaries without stopping at "dot" and/or other characters
例如给定这样的字符串:
随机词,随机字符##?,一些点。用户名 bob.1234 其他东西
我目前正在使用这个正则表达式来捕获用户名(bob.1234):
1
| \\busername (.+?)(,| |$) |
但是我的代码需要一个只有一个捕获组的正则表达式,因为当有多个捕获组时,python 的 re.findall 返回不同的东西。像这样的东西几乎可以工作,除了它会捕获用户名"bob"而不是"bob.1234":
有人知道是否有一种方法可以使用单词边界同时忽略点并且不使用多个捕获组?
注意事项:
-
有时用户名后面有逗号
-
有时用户名后面有一个空格
-
有时字符串以用户名结尾
- 试试 \\busername ([^ ,]+)
-
或者也许 username (\\S+)\\b
-
两者都在工作,伙计们!我没有想过完全不同的方向Wiktor,好主意!你们愿意发布解决方案以便我接受吗?不知道该给谁,但两者都很完美
-
如果用户名不以句点或字母和数字以外的任何内容结尾,那么我可以发布我的作为答案。
-
实际上 Revo,它也适用于以下划线结尾的用户名
-
@NaturalBornCamper。这些用户名可以包含哪些特定的字符集?
-
我猜 Wiktor 的解决方案在这里会更好,因为它也接受以点结尾的用户名。但是,如果您还想发布 Revo,我会添加支持答案(我想我仍然可以这样做),它可能会帮助其他人
-
是的,但说明不是那么重要。那些说将导致意想不到的匹配。
-
@ekhumoro 我不知道,这就是为什么我把"和/或"放在问题中,但我猜是字母数字、下划线、点。 Wiktor 的解决方案仍然有效,如果用户名中出现更多字符,我可以自定义它
-
@revo 我没有看到任何以点结尾的用户名,实际上我什至没有考虑过,真丢脸。但我猜它*可能发生
-
@NaturalBornCamper。我问是因为 revo 的正则表达式将匹配例如username b,,,!@=++&&=4。
-
他不是在验证,而是在匹配。这两者彼此不同。 @ekhumoro
-
@revo。规范说用户名后面可以跟一个逗号,然后是"其他东西"。给定示例 username bob.1234,otherstuff,您的正则表达式不会产生 bob.1234,因为它将匹配逗号及其后面的所有内容,直到下一个单词边界。
-
这是否意味着逗号后除了空格字符之外还有其他内容? @ekhumoro
-
@revo。我不知道 - 这就是我要求 OP 澄清的原因。您的正则表达式可能没问题,但它依赖于使用明确分隔符很好地格式化输入。如果用户名可以包含一些可能的分隔符,那可能会使事情复杂化。
-
在提出建议之前,我在阅读案例时查看了主题字符串格式。当用户名以逗号结尾时,它后面可能紧跟着非空白字符,这是无法理解的。否则,是的,正则表达式将无法正常工作。 @ekhumoro
-
您不能使用否定类,它必须是 1 个或更多... []+。然后它不能处理字符串结尾。如果您使用 []+? 它只会匹配 1 个字符。如果您使用 []*? 它不会匹配任何字符(因为它在末尾)。所以,下课了。您可以将您的正则表达式更改为此 \\busername (.+?)(?:,| |$) ,它将匹配您想要的。请注意,当您使用否定类时,会引入大量它将匹配的字符。我会尽量不要想太多...
-
@sln 为什么当用户名遇到结尾时 []+ 不能处理字符串结尾?
-
@revo - []+ 用于说明量词。示例 \\busername (.+?)[ ,]+ 如果您严格使用否定类而不是 .+? 匹配大量字符(可能没问题)。
-
@ekhumoro 是对的,它的格式不是"总是",它可能以用户名结尾,后面可能有一个空格,后面可能有一个逗号,然后没有空格.. 但是 Wiktor 的到目前为止,解决方案对每个样本都很有效,谢谢大家!
\\busername (.+?)(,| |$) 模式包含 2 个捕获组,一旦找到匹配项,re.findall 将返回一个元组列表。请参阅 findall 参考:
If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result unless they touch the beginning of another match.
所以,这里有三种方法:
使用 (?:...) 非捕获组而不是捕获组:re.findall(r'\\busername (.+?)(?:,| |$)', s)。它将消耗一个 , 或空间,但由于只返回捕获的部分并且预计不会重叠匹配,所以没关系。
请改用积极的前瞻:re.findall(r'\\busername (.+?)(?=,| |$)', s)。不会消耗空格和逗号,这是与第一种方法的唯一区别。
您可以将 (.+?)(,| |$) 变成一个简单的否定字符类 [^ ,]+,它匹配一个或多个字符而不是空格或逗号。如果 , 或 username 之后没有空格,它将匹配到字符串末尾。
- 仅供参考:如果用户名中出现更多字符,我可以对其进行自定义。是的,一旦为用户名模式制定了最终规范,这可能是必要的。
-
对不起,我经常这样做,这次忘了! ;)