如何用正则表达式匹配整个单词?

Posted

技术标签:

【中文标题】如何用正则表达式匹配整个单词?【英文标题】:How to match a whole word with a regular expression? 【发布时间】:2013-03-29 14:07:24 【问题描述】:

我无法为以下场景找到正确的正则表达式:

让我们说:

a = "this is a sample"

我想匹配整个单词 - 例如 match "hi" 应该返回 False,因为 "hi" 不是一个单词,"is" 应该返回 True,因为左侧和右侧都没有字母字符。

【问题讨论】:

我重新打开了这个问题,因为它被关闭为重复错误的帖子。 【参考方案1】:

试试

re.search(r'\bis\b', your_string)

来自the docs:

\b 匹配空字符串,但只匹配单词的开头或结尾。

请注意,re 模块将“单词”简单定义为“字母数字或下划线字符序列”,其中“字母数字”取决于区域设置或 unicode 选项。

另请注意,如果没有原始字符串前缀,\b 将被视为“退格”而不是正则表达式单词边界。

【讨论】:

谢谢,我添加了 flags=re.IGNORECASE 在这个语句中需要什么 r - re.search(r'\bis\b', your_string) ? @user2161049: test! 不是一个词,根据我所知道的任何定义。有趣的是,它确实适用于收缩:re.search(r"\bisn't\b", "it isn't bad") 返回匹配项。 奇怪的是,它不适用于终端省略:re.search(r"\bisn'\b", "it isn' bad") 返回不匹配。特殊的不是撇号,而是位置。 word(模式)可以在其中包含标点符号,但不能在结尾或开头。 test!a 可以匹配某些东西,但 test! 不能。 为什么我得到的是\x08 而不是\b【参考方案2】:

尝试在正则表达式模块中使用“单词边界”字符类re

x="this is a sample"
y="this isis a sample."
regex=re.compile(r"\bis\b")  # For ignore case: re.compile(r"\bis\b", re.IGNORECASE)

regex.findall(y)
[]

regex.findall(x)
['is']

来自re.search()的文档。

\b 匹配空字符串,但只匹配单词的开头或结尾

...

例如,r'\bfoo\b' 匹配 'foo''foo.''(foo)''bar foo baz',但不匹配 'foobar''foo3'

【讨论】:

【参考方案3】:

我认为使用给出的答案并没有完全实现 OP 所需的行为。具体来说,没有实现所需的布尔值输出。 do 给出的答案有助于说明这个概念,我认为它们非常好。也许我可以通过说明我认为 OP 使用所使用的示例来说明我的意思,因为以下原因。

给出的字符串是,

a = "this is a sample"

OP 然后声明,

我想匹配整个单词 - 例如匹配 "hi" 应该返回 False 因为 "hi" 不是一个单词...

据我了解,参考是搜索标记 "hi",因为它可以在单词 "this" 中找到。如果有人要搜索字符串 a 来查找 word "hi",他们应该会收到 False 作为响应。

OP 继续,

...和"is" 应该返回True,因为左右两边都没有字母字符。

在这种情况下,引用是在单词"is" 中找到的搜索标记"is"。我希望这有助于澄清我们为什么使用单词边界。其他答案的行为是“不返回一个词,除非该词是由它自己找到的——不在其他词的内部”。 “单词边界”shorthand character class 很好地完成了这项工作。

到目前为止,仅在示例中使用了单词"is"。我认为这些答案是正确的,但我认为还有更多问题的基本含义需要解决。应注意其他搜索字符串的行为以理解该概念。换句话说,我们需要概括@georg 使用re.match(r"\bis\b", your_string) 的(优秀)答案@OmPrakash 的答案中也使用了相同的r"\bis\b" 概念,他通过展示开始概括讨论

>>> y="this isis a sample."
>>> regex=re.compile(r"\bis\b")  # For ignore case: re.compile(r"\bis\b", re.IGNORECASE)
>>> regex.findall(y)
[]

假设应该表现出我讨论过的行为的方法被命名为

find_only_whole_word(search_string, input_string)

然后应该会出现以下行为。

>>> a = "this is a sample"
>>> find_only_whole_word("hi", a)
False
>>> find_only_whole_word("is", a)
True

再一次,这就是我对 OP 问题的理解。通过@georg 的回答,我们朝着这种行为迈出了一步,但这有点难以解释/实施。机智

>>> import re
>>> a = "this is a sample"
>>> re.search(r"\bis\b", a)
<_sre.SRE_Match object; span=(5, 7), match='is'>
>>> re.search(r"\bhi\b", a)
>>>

第二个命令没有输出。 @OmPrakesh 的有用答案显示输出,但不显示 TrueFalse

以下是预期行为的更完整示例。

>>> find_only_whole_word("this", a)
True
>>> find_only_whole_word("is", a)
True
>>> find_only_whole_word("a", a)
True
>>> find_only_whole_word("sample", a)
True
# Use "ample", part of the word, "sample": (s)ample
>>> find_only_whole_word("ample", a)
False
# (t)his
>>> find_only_whole_word("his", a)
False
# (sa)mpl(e)
>>> find_only_whole_word("mpl", a)
False
# Any random word
>>> find_only_whole_word("applesauce", a)
False
>>>

这可以通过以下代码来完成:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#@file find_only_whole_word.py

import re

def find_only_whole_word(search_string, input_string):
  # Create a raw string with word boundaries from the user's input_string
  raw_search_string = r"\b" + search_string + r"\b"

  match_output = re.search(raw_search_string, input_string)
  ##As noted by @OmPrakesh, if you want to ignore case, uncomment
  ##the next two lines
  #match_output = re.search(raw_search_string, input_string, 
  #                         flags=re.IGNORECASE)

  no_match_was_found = ( match_output is None )
  if no_match_was_found:
    return False
  else:
    return True

##endof:  find_only_whole_word(search_string, input_string)

下面是一个简单的演示。从保存文件的同一目录运行 Python 解释器,find_only_whole_word.py

>>> from find_only_whole_word import find_only_whole_word
>>> a = "this is a sample"
>>> find_only_whole_word("hi", a)
False
>>> find_only_whole_word("is", a)
True
>>> find_only_whole_word("cucumber", a)
False
# The excellent example from @OmPrakash
>>> find_only_whole_word("is", "this isis a sample")
False
>>>

【讨论】:

请注意,如果只需要“真实”的整个单词,则必须对输入进行清理。 &gt;&gt;&gt; find_only_whole_word("another sentence", "To show this, I will use another sentence.") 返回True。这可能是所期望的行为,所以我将保持原样。 如果你想要一个使用@OsPrakesh 使用的findall 方法的单行:&gt;&gt;&gt; len(re.findall(r"\bhi\b", "This IS a sample.", flags=re.IGNORECASE)) 返回False。任何其他需要的字符串都可以放在\bs 之间。【参考方案4】:

正则表达式的问题在于,如果您要在另一个字符串中搜索的 hte 字符串包含正则表达式字符,它会变得复杂。任何带括号的字符串都会失败。

这段代码会找到一个单词

 word="is"
    srchedStr="this is a sample"
    if srchedStr.find(" "+word+" ") >=0  or \
       srchedStr.endswith(" "+word):
        <do stuff>

条件的第一部分搜索两边各有一个空格的文本,第二部分捕获字符串结尾的情况。注意 endwith 是布尔值,而 find 返回一个整数

【讨论】:

另外,我看到已经有一个被接受的答案 - 您可能想要删除您的答案并恢复由于投票而导致的声誉。 @davejagoda 会删除答案恢复他/她的声誉吗? @silentphoenix 我相信是这样的:meta.stackexchange.com/questions/5221/… 第一段不正确。目标字符串可以有任意内容。 如果单词出现在目标字符串的开头,则不起作用。它还假设单词总是被空格包围,这通常不是真的。

以上是关于如何用正则表达式匹配整个单词?的主要内容,如果未能解决你的问题,请参考以下文章

如何用js匹配url的正则表达式

正则表达式

如何用正则表达式匹配IP地址

如何用正则表达式在JS中匹配出相应的拓展名?

如何用正则表达式匹配汉字

如何用正则表达式匹配指定字符开始和指定字符结束?