Python - все строки и номера строк, в которых находится строка во входном файле - PullRequest
0 голосов
/ 27 октября 2018

Я хочу напечатать все строки, в которых встречается строка во входном файле, вместе с номерами строк. Пока что я написал код, показанный ниже. Это работает, но не так, как я хотел:

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

Ответы [ 3 ]

0 голосов
/ 27 октября 2018

Возможно, вы захотите использовать маркер границы слова \b. Это пустое совпадение для переходов между \w и \W. Если вы хотите, чтобы ваши ключевые слова были буквальными строками, вам сначала нужно экранировать . Вы можете объединить все в одно регулярное выражение, используя |:

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

OR

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)

OR

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)

Если вам не нравится этот порядок, вы всегда можете распечатать его в каком-то другом порядке после того, как совпадете.

0 голосов
/ 27 октября 2018

Вопрос : ключевое слово типа "Sog" также находит Sogan ... Я хочу только токены между пробелами.... как я могу добавить это регулярное выражение в этот код.

Создайте regex с вашим keywords, используйте разделитель 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

0 голосов
/ 27 октября 2018

Вы можете использовать следующее регулярное выражение:

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. Регулярное выражение Синтаксис
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...