12

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

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

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

我想要做的是添加另一个正则表达式来排除字符串中的一个字符。我想打印出所有有五个字母的单词,一个“z”,但 -不是- 一个“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,

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

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

4

2 回答 2

28

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

[^a-z]

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

逐字解释:

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

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

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

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

于 2013-11-12T09:06:23.193 回答
10

您可以使用negative look arounds. 这不是正则表达式特别快的任务,但它确实有效。要匹配除 sub-string 之外的所有内容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 就足够了。更长和更复杂的否定匹配将需要使用这种方法。

于 2013-11-12T09:18:15.693 回答