Python输入fi中字符串出现的所有行和行号

2024-09-27 07:29:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我想打印输入文件中出现字符串的所有行,以及行号。到目前为止,我编写了如下代码。它在工作,但不是我想要的方式:

def index(filepath, keyword):

    with open(filepath) as f:
        for lineno, line in enumerate(f, start=1):
            matches = [k for k in keyword if k in line]
            if matches:
                result = "{:<15} {}".format(','.join(matches), lineno)
                print(result)
                print (line)

index('deneme.txt', ['elma'])

输出如下:

elma            15
Sogan+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elma+Noun ve+Conj turunçgil+Noun+A3pl ihracat+Noun+P3sg+Dat devlet+Noun destek+Noun+P3sg ver+Verb+Pass+Prog2+Cop .+Punc  

到目前为止还不错,但是当我输入像"Sog"这样的关键字时,它也会找到Sogan,但我不想这样,我只想检查空白之间的标记。我想我需要为此编写正则表达式,我得到了一个,但我现在不知道如何将正则表达式添加到代码中。你知道吗

r'[\w+]+'

Tags: 代码inforindexiflineresultkeyword
3条回答

可以使用以下正则表达式:

import re

lines = [
    'Sogan+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elma+Noun ve+Conj turunçgil+Noun+A3pl ihracat+Noun+P3sg+Dat devlet+Noun destek+Noun+P3sg ver+Verb+Pass+Prog2+Cop .+Punc',
    'Sog+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elma+Noun ve+Conj turunçgil+Noun+A3pl ihracat+Noun+P3sg+Dat devlet+Noun destek+Noun+P3sg ver+Verb+Pass+Prog2+Cop .+Punc',
]

keywords = ['Sog']
pattern = re.compile('(\w+)\+')

for lineno, line in enumerate(lines):
    words = set(m.group(1) for m in pattern.finditer(line))  # convert to set for efficiency
    matches = [keyword for keyword in keywords if keyword in words]
    if matches:
        result = "{:<15} {}".format(','.join(matches), lineno)
        print(result)
        print(line)

输出

Sog             1
Sog+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elma+Noun ve+Conj turunçgil+Noun+A3pl ihracat+Noun+P3sg+Dat devlet+Noun destek+Noun+P3sg ver+Verb+Pass+Prog2+Cop .+Punc

解释

模式'(\w+)\+'后跟+字符的任何一组字母,+是特殊字符,因此需要对其进行转义,以便匹配。然后使用group来提取匹配的组(即字母组)。你知道吗

进一步

  1. 正则表达式syntax

您可能需要使用单词边界标记\b。这是\w\W之间转换的空匹配。如果希望关键字是文本字符串,则必须首先escape它们。可以使用|将所有内容组合成一个正则表达式:

pattern = re.compile(r'\b(' + '|'.join(map(re.escape, keyword)) + r')\b')

或者

pattern = re.compile(r'\b(?' + '|'.join(re.escape(k) for k in keyword) + r')\b')

计算匹配项现在变得更容易了,因为您可以使用^{}而不是自己理解:

matches = pattern.finditer(line)

由于每个匹配项都包含在一个组中,因此打印并不困难:

result = "{:<15} {}".format(','.join(m.group() for m in matches), lineno)

或者

result = "{:<15} {}".format(','.join(map(re.Match.group(), matches)), lineno)

当然,别忘了

import re

角盒

如果关键字是具有相同前缀的彼此的子集,请确保先出现较长的关键字。例如,如果你有

keyword = ['foo', 'foobar']

正则表达式将是

\b(foo|foobar)\b

当您遇到一行中有foobar时,foo将与之成功匹配,然后与\b'. This is documented behavior of|`匹配失败。解决方案是在构造表达式之前,通过减小长度对所有关键字进行预排序:

keywords.sort(key=len, reversed=True)

或者,如果可以使用非列表输入:

keywords = sorted(keywords, key=len, reversed=True)

如果您不喜欢这个顺序,您可以在匹配后以其他顺序打印它们。你知道吗

Question: a keyword like "Sog" it also finds the Sogan ... I only want tokens between whitespaces. ... how can i add that regex to this code.

用你的keywords构建一个regex,用or |分隔符表示多个keywords。你知道吗

例如:

import re

def index(lines, keyword):
    rc = re.compile(".*?(({})\+.+?\s)".format(keyword))

    for i, line in enumerate(lines):
        match = rc.match(line)
        if match:
            print("lines[{}] match:{}\n{}".format(i, match.groups(), line))

if __name__ == "__main__":
    lines = [
    'Sogan+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elmaro+Noun ve+Conj ... (omitted for brevity)',
    'Sog+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elma+Noun ve+Conj ... (omitted for brevity)',
]
    index(lines, 'elma')
    index(lines, 'Sog|elma')

Output:

lines[1] match:('elma+Noun ', 'elma')
Sog+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elma+Noun ve+Conj ... (omitted for brevity)
lines[1] match:('Sog+Noun ', 'Sog')
Sog+Noun ,+Punc domates+Noun ,+Punc patates+Noun ,+Punc elma+Noun ve+Conj ... (omitted for brevity)

用Python:3.5测试

相关问题 更多 >

    热门问题