簡體   English   中英

Python-輸入文件中出現字符串的所有行和行號

[英]Python - All the lines and line numbers in which string occurs in the input file

我想打印輸入文件中出現字符串的所有行以及行號。 到目前為止,我編寫了如下所示的代碼。 它正在工作,但不是我想要的方式:

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+]+'

您可以使用以下正則表達式:

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. 正則表達式語法

您可能需要使用單詞邊界標記\\b 這是\\w\\W之間的過渡的空匹配。 如果您希望關鍵字是文字字符串,則必須先對其進行轉義 您可以使用|將所有內容組合為一個正則表達式

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')

現在,計算比賽要容易一些,因為您可以使用finditer而不是自己進行理解:

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失敗\\b'. This is documented behavior of \\b'. This is documented behavior of |` \\b'. This is documented behavior of 解決方案是在構造表達式之前,通過減小長度來對所有關鍵字進行預排序:

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

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

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

如果您不喜歡此順序,則始終可以在匹配后按其他順序打印它們。

問題 :像“ Sog”這樣的關鍵字也可以找到Sogan...。我只希望空格之間有標記。 ...我如何將該正則表達式添加到此代碼中。

使用您的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')

輸出

 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM