Условный поиск и замена в файле Python - PullRequest
1 голос
/ 30 января 2011

У меня большой текстовый файл размером более 10 МБ, когда требуется условный поиск и замена. Я хочу заменить каждый экземпляр «a» внутри файла на «ā», если символ после «a» является либо «r», либо «m», либо «n», либо «u».

Например: Входной файл

Hamro sano ghar holata.

Выходной файл

Hāmro sāno ghār holata.

EDIT

Спасибо, ребята, похоже, хорошо работает. Но, похоже, он не работает с нелатинскими символами, такими как индийские скрипты: Рабочий скрипт для латинских символов:

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import re
input = "Hamro sano ghar holata."
regex = re.compile(ur'a([rmnu])')
print regex.sub(ur'ā\1', input)

Script1 (для Деванагари) НЕ РАБОТАЕТ

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import re
input ="संगम"
regex = re.compile(ur'ं([कखगघ])')
print regex.sub(r'ङ्\1', input)

Script2 (добавлен юникод) НЕ РАБОТАЕТ

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import re
input =u"संगम"
regex = re.compile(ur'ं([कखगघ])', re.UNICODE)
print regex.sub(r'ङ्\1', input)

Ожидаемый результат: ं заменено на ङ्, поскольку ग следует ं, т.е. सङ्गम

Ответы [ 3 ]

3 голосов
/ 30 января 2011

вам нужно простое регулярное выражение здесь. Как то так?

>>> import re
>>> input = "Hamro sano ghar holata."
>>> regex = re.compile(ur'a([rmnu])') # the part in parens is remembered
>>> print regex.sub(ur'ā\1', input) # replace by ā plus remembered part
Hāmro sāno ghār holata.

Edit:

сначала немного фона:

Это сложная задача на намного с Devanāgarī (देवनागरी) не из-за кодировки, а потому, что правила объединения глифов чрезвычайно сложны (по крайней мере, из-за стандарты латинского алфавита). Я пишу этот ответ, например, на Chrome, который все еще не может правильно составить Devanāgarī для «Devanāgarī» (он получает диакритическую отметку для «е» в неправильном месте - он делает то же самое с дифтонгом «ай»).

То, как эти глифы объединяются механизмом рендеринга текста, называется «лигатурами», и для Деванагари они очень сложны с технической точки зрения. Если вы добавите еще больше колоссальных усложнений, введенных 101 ( saṃdhi - снова, рендеринг Chrome возвращает bindu , который представляет anusvāra в неправильном месте), вы можете видеть, что то, что вы пытаетесь сделать здесь, может очень быстро сделать чрезвычайно .

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

>>> import re
>>> inputString = u"संगम"
>>> regex = re.compile(ur'\u0902(?=[कखगघ])')
>>> print regex.sub(ur'ङ\u094d', inputString)
सङ्गम

В регулярных выражениях я заменил anusvāra и virāma (хинди: halant ) на экранированное значение Unicode, для ясности. Учитывая то, как работают лигатуры, возможно, что в некоторых случаях это будет пропущено, но я переключил мой пример на использование предвкушения, как в примере с @ Kabie (который в любом случае, вероятно, является лучшим выбором), чтобы смягчить это, насколько это возможно.

2 голосов
/ 30 января 2011
re.sub(r'a(?=[rmnu])',r'ā',"Hamro sano ghar holata.")
1 голос
/ 30 января 2011

Для вашего большого текстового файла вы должны скопировать оригинал, заменить символы и написать новый файл с обновленными строками.Вы должны читать только кусок за раз, а не весь файл.(Хотя на современном компьютере вы могли бы просто отбросить все 10 МБ за один раз.)

Простой способ сделать это - использовать объект файла в качестве итератора;это возвращает по одной строке из файла за раз.

import re
pat = re.compile(ur'a([rmnu])') # pre-compile regex pattern for speed

f = open("corrected_file.txt", "wb")

for line in open("big_file_10mb.txt", "rb"):
    line = pat.sub(ur'ā\1', line)
    f.write(line)

f.close()

Если вы хотите вылить весь файл за один раз, вы можете использовать функцию метода .read():

f = open("big_file_10mb.txt", "rb")
s = f.read()  # read entire file contents
f.close()
s = pat.sub(ur'ā\1', s)  # replace over entire file contents
f = open("corrected_file.txt", "wb")
f.write(s)  # write entire file contents
f.close(s)

Не делайте так, если у вас нет веских причин.Линейно-ориентированная версия проста для понимания и работает намного лучше, когда файлы больше по сравнению с объемом памяти на вашем компьютере.

В книге Dive Into Python есть глава, объясняющая регулярные выражения:

http://diveintopython3.ep.io/regular-expressions.html

Вы хотите прочитать Юникод и заменить символы Юникода.Вам нужно будет определить исходную кодировку файла, прочитать его, преобразовать в Unicode, выполнить подстановку, а затем записать его в правильной кодировке.Или вы можете использовать специальный модуль «кодеки»;codecs.open () предоставит вам файловый объект, который автоматически преобразует вас.

Вот документ с инструкциями по Unicode для Python:

http://docs.python.org/howto/unicode.html

Итак, давайте предположим, что текстовый файл, который вы хотите прочитать, закодирован в UTF-8.Я думаю, что это будет работать для вас:

import codecs
import re

pat = re.compile(ur'a([rmnu])') # pre-compile regex pattern for speed

f = codecs.open("corrected_file.txt", mode="wb", encoding="utf-8")

for line in codecs.open("big_file_10mb.txt", mode="rb", encoding="utf-8"):
    line = pat.sub(ur'ā\1', line)
    f.write(line)

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