【问题标题】:using regular expressions to exclude characters in a string search?使用正则表达式排除字符串搜索中的字符?
【发布时间】:2013-11-24 08:06:43
【问题描述】:

我正在使用 Python 2.7.2 脚本来查找我用作主单词列表的文本文件中的单词列表。

我在终端窗口中调用脚本,输入任意数量的正则表达式,然后运行脚本。

所以,如果我传入两个正则表达式“^.....$”和“.*z”,它将打印每个包含至少一个“z”的五个字母的单词。

我想要做的是添加另一个正则表达式来排除字符串中的一个字符。我想打印出所有有五个字母的单词,一个“z”,但是 -not- 一个“y”。

代码如下:

import re
import sys

def read_file_to_set(filename):
    words = None
    with open(filename) as f:
        words = [word.lower() for word in f.readlines()]
    return set(words)

def matches_all(word, regexes):
    for regex in regexes:
        if not regex.search(word):
            return False
    return True

if len(sys.argv) < 3:
    print "Needs a source dictionary and a series of regular expressions"
else:
    source = read_file_to_set(sys.argv[1])
    regexes = [re.compile(arg, re.IGNORECASE)
               for arg in sys.argv[2:]]
    for word in sorted(source):
        if matches_all(word.rstrip(), regexes):
            print word,

我可以在传递给程序的正则表达式上添加哪些修饰符,以允许我从它打印的字符串中排除某些字符?

如果不可能,代码中需要实现什么?

【问题讨论】:

    标签: python regex string


    【解决方案1】:

    指定一个不匹配的字符是这样完成的(这匹配除了小写字母之外的任何字符):

    [^a-z]
    

    所以要匹配一个不包含“y”的字符串,正则表达式为:^[^y]*$

    逐字解释:

    ^ 表示“开始”,如果它出现在正则表达式的开头。 同样,$ 表示“结束”,如果它出现在末尾。 [abAB] 匹配范围内或范围内的任何字符。例如,匹配任何十六进制字符(大写或小写):[a-fA-F0-9]

    * 表示0 个或多个前面的表达式。 作为[] 中的第一个字符,^ 有不同的含义:它的意思是“不”。所以[^a-fA-F0-9] 匹配任何非十六进制字符。

    当您在^$ 之间放置一个模式时,您会强制正则表达式与字符串完全匹配(在模式之前或之后都没有)。结合所有这些事实:

    ^[^y]*$ 表示字符串正好是 0 个或多个不是“y”的字符。 (要做一些更有趣的事情,你可以检查非数字:^[^0-9]$

    【讨论】:

    • 这正是我想要的!你介意解释一下“^[^y]*$”中的每个字符在做什么吗?我才刚刚开始使用计算机编程/Python,并且我已经在正则表达式的文档中看到了这些字符中的每一个,但无法考虑像这样将它们组合起来以获得该结果。
    • 这是非常有用的解释,谢谢。您能解释一下如何制作它,以便您可以组合 2 个正则表达式“NOT”/排除语句吗?例如,如果你想匹配一些不是 y 并且它也不是 q 的字符串会是什么样子?
    • @EazyC 如果排除是字符,它只是 [^yq]*。如果是完整的字符串,它实际上是相当困难的。我不知道如何随意,但我认为你可以通过消极的前瞻/后瞻来做到这一点。正则表达式是关于匹配字符的,但是当涉及到 not 匹配字符时,它们就没有那么强大了。因此,一些正则表达式引擎甚至不支持前瞻/后瞻。 (不同之处在于它们匹配的不是当前字符,而是潜在的未来/以前的字符。)因此,要搜索“不是这个和那个”,您需要负前瞻/后瞻。
    【解决方案2】:

    您可以使用negative look arounds 完成此操作。这不是正则表达式特别快的任务,但它确实有效。要匹配除子字符串 foo 之外的所有内容,您可以使用:

    >>> my_regex = re.compile(r'^((?!foo).)*$', flags = re.I)
    >>> print my_regex.match(u'IMatchJustFine')
    <_sre.SRE_Match object at 0x1034ea738>
    >>> print my_regex.match(u'IMatchFooFine')
    None
    

    正如其他人所指出的,如果您只匹配一个字符,那么一个简单的 not 就足够了。更长更复杂的否定匹配需要使用这种方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-17
      • 1970-01-01
      • 2014-02-08
      • 1970-01-01
      • 2012-02-17
      • 1970-01-01
      • 2017-04-13
      • 1970-01-01
      相关资源
      最近更新 更多