Регулярное выражение для удаления разрывов строк - PullRequest
12 голосов
/ 22 февраля 2011

Я полный новичок в Python, и я застрял с проблемой регулярных выражений.Я пытаюсь удалить символ разрыва строки в конце каждой строки в текстовом файле, но только если он следует за строчной буквой, то есть [a-z].Если конец строки заканчивается строчной буквой, я хочу заменить символ перевода строки / новой строки пробелом.

Это то, что я получил до сих пор:

import re
import sys

textout = open("output.txt","w")
textblock = open(sys.argv[1]).read()
textout.write(re.sub("[a-z]\z","[a-z] ", textblock, re.MULTILINE) )
textout.close()

Ответы [ 3 ]

23 голосов
/ 22 февраля 2011

Попробуйте

re.sub(r"(?<=[a-z])\r?\n"," ", textblock)

\Z соответствует только в конце строки, после последнего переноса строки, так что это определенно не то, что вам нужно здесь. \z не распознается механизмом регулярных выражений Python.

(?<=[a-z]) - это положительное утверждение за 101 *, которое проверяет, является ли символ перед текущей позицией символом ASCII в нижнем регистре. Только тогда движок регулярных выражений будет пытаться сопоставить разрыв строки.

Кроме того, всегда используйте необработанные строки с регулярными выражениями. Облегчает работу с обратными слешами.

2 голосов
/ 22 февраля 2011

Так же, как альтернативный ответ, хотя он занимает больше строк, я думаю, что следующее может быть более понятным, поскольку регулярное выражение проще:

import re
import sys

with open(sys.argv[1]) as ifp:
    with open("output.txt", "w") as ofp:
        for line in ifp:
            if re.search('[a-z]$',line):
                ofp.write(line.rstrip("\n\r")+" ")
            else:
                ofp.write(line)

... и это позволяет избежать загрузки всего файла встрока.Если вы хотите использовать меньше строк, но по-прежнему избегаете позитивного просмотра, вы можете сделать следующее:

import re
import sys

with open(sys.argv[1]) as ifp:
    with open("output.txt", "w") as ofp:
        for line in ifp:
            ofp.write(re.sub('(?m)([a-z])[\r\n]+$','\\1 ',line))

Части этого регулярного выражения:

  • (?m) [включитьмногострочное сопоставление]
  • ([a-z]) [соответствует одному символу в нижнем регистре в качестве первой группы]
  • [\r\n]+ [соответствует одному или нескольким возвратам каретки или переводу строки, чтобы охватить \n,\r\n и \r]
  • $ [соответствует концу строки]

... и если это соответствует строке, строчная буква и окончание строкизаменяется на \\1, за которым следует строчная буква, за которой следует пробел.

1 голос
/ 22 февраля 2011

моя точка зрения заключалась в том, что отказ от использования положительного взгляда может сделать код более читабельным

ОК.Хотя лично я не нахожу это менее читабельным.Это дело вкуса.

В вашем редактировании:

  • Во-первых, (? M) не требуется, поскольку для строки вifp: выбирает по одной строке за раз, поэтому в конце каждой строки указывается только одна новая строка

  • Во-вторых, $ в том виде, в котором она размещена, не имеет никакой полезности, потому что он всегда будет соответствовать концу строки строки.

В любом случае, принимая вашу точку зрения, я нашел два способа избежать утверждения о взгляде сзади:

with open(sys.argv[1]) as ifp:
    with open("output.txt", "w") as ofp:
        for line in ifp:
            ante_newline,lower_last = re.match('(.*?([a-z])?$)',line).groups()
            ofp.write(ante_newline+' ' if lower_last else line)

и

with open(sys.argv[1]) as ifp:
    with open("output.txt", "w") as ofp:
        for line in ifp:
            ofp.write(line.strip('\r\n')+' ' if re.search('[a-z]$',line) else line)

вторая лучше: только одна строка, простое соответствие для проверки, нет необходимости в группах (), естественно логика

РЕДАКТИРОВАТЬ: оЯ понимаю, что этот второй код - просто ваш первый код, переписанный в одну строку, Longair

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...