[英]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提取匹配的組(即字母組)。
進一步
您可能需要使用單詞邊界標記\\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.