Найти - Пользователи
Полная версия: Правка текстового файла поблоково.
Начало » Python для новичков » Правка текстового файла поблоково.
1
knoppix
Друзья, я не настоящий сварщик, но у меня есть стремление учиться. Есть задача, которую я могу решить на bash, но не знаю как к ней подступиться на python, помогите, пожалуйста советом.

Итак, есть текстовый файл, в котором повторяются блоки вида:

EOD
PROFILE R_Ti_174 TYPE 1
SNAPPING PARAMETERS 5
5494510.000 1084246.625 0 14 2560.31 5855.34 5855.34 5855 I 2250 TrebsTito R_Ti_174
5494309.500 1084098.875 0 15 2476.59 5845.37 5845.37 5845 I 2250 TrebsTito R_Ti_174
5494300.500 1084402.750 1 14 2664.88 5852.30 5852.30 5852 I 2260 TrebsTito R_Ti_174
5494010.500 1084189.000 1 15 2476.50 5837.89 5837.89 5838 I 2260 TrebsTito R_Ti_174

Изменяются в этих блоках лишь записи вида R_Ti_174, различные для каждого блока. Требуется для каждого блока дописать к EOD эту запись вида R_Ti_174.
То есть получиться должно следующее:
EOD R_Ti_174
PROFILE R_Ti_174 TYPE 1
SNAPPING PARAMETERS 5
5494510.000 1084246.625 0 14 2560.31 5855.34 5855.34 5855 I 2250 TrebsTito R_Ti_174
5494309.500 1084098.875 0 15 2476.59 5845.37 5845.37 5845 I 2250 TrebsTito R_Ti_174
5494300.500 1084402.750 1 14 2664.88 5852.30 5852.30 5852 I 2260 TrebsTito R_Ti_174
5494010.500 1084189.000 1 15 2476.50 5837.89 5837.89 5838 I 2260 TrebsTito R_Ti_174

На bash я делал так:
1. ищем первое вхождение EOD$
2. вычленяем из третьей строки после этого вхождения наше значение R_Ti_174
3. делаем замену для первого вхождения EOD$ на EOD R_Ti_174
4. Повторяем операцию, и за счет того, что мы использовали в вхождении $, то обработанный блок уже не вернется во вхождение.

Это работает, но это не элегантно. Хочется элегантно, и в python. Я не прошу эту задачу за меня решать, просто скажите так, на словах, как это сделать красиво?





py.user.next
Используй теги кода.
Приведи пример входного блока и выходного блока, который получается.
doza_and
Если файл маленький то:
import re
data=open("reg.txt","r").read()
rx=re.compile(r"EOD(.+?)TrebsTito (\w+)",re.M|re.DOTALL)
data1=re.sub(rx,r"EOD \2\1TrebsTito \2",data)
open("reg1.txt","w").write(data1)
Может конечно это и не очень красиво…
Непонятно почему из 3 строчки. Во второй тоже есть.
Без регулярок
with open("reg.txt","r") as f:
    for i in f:
        i=i.rstrip()
        if i=="EOD":
            j=f.next().rstrip()
            i+=" "+j.split()[1]
            print(i)
            print(j)
        else:
            print(i)
knoppix
doza_and, спасибо, это работает.
Можешь объяснить что происходит в 3,4 строчках кода?
И что будет, если файл большой?
doza_and
knoppix
Можешь объяснить что происходит в 3,4 строчках кода?
Во второй задается шаблон поиска при помощи регулярных выражений. При этом Флаги выставляем так, чтобы регулярное выражение работало не построчно а во всем тексте. Это чтобы его действие продлилось на несколько строк и можно было выцепить результат из следующих строчек
В строке 4 происходит замена с использованием этого шаблона сразу для всего файла.
Я привел второй подход. можно сказать более традиционный.
knoppix
doza_and
Непонятно почему из 3 строчки. Во второй тоже есть.

По условию задачи, нужно брать из третьей строчки. Спасибо тебе!
py.user.next
>>> import re
>>> 
>>> text = """
... EOD
... PROFILE R_Ti_174 TYPE 1
... SNAPPING PARAMETERS 5
... 5494510.000 1084246.625 0 14 2560.31 5855.34 5855.34 5855 I 2250 TrebsTito R_Ti_174
... 5494309.500 1084098.875 0 15 2476.59 5845.37 5845.37 5845 I 2250 TrebsTito R_Ti_174
... 5494300.500 1084402.750 1 14 2664.88 5852.30 5852.30 5852 I 2260 TrebsTito R_Ti_174
... 5494010.500 1084189.000 1 15 2476.50 5837.89 5837.89 5838 I 2260 TrebsTito R_Ti_174
... 
... EOD
... PROFILE R_Ti_175 TYPE 1
... SNAPPING PARAMETERS 5
... 5494510.000 1084246.625 0 14 2560.31 5855.34 5855.34 5855 I 2250 TrebsTito R_Ti_175
... 5494309.500 1084098.875 0 15 2476.59 5845.37 5845.37 5845 I 2250 TrebsTito R_Ti_174
... 5494300.500 1084402.750 1 14 2664.88 5852.30 5852.30 5852 I 2260 TrebsTito R_Ti_174
... 5494010.500 1084189.000 1 15 2476.50 5837.89 5837.89 5838 I 2260 TrebsTito R_Ti_174
... """
>>> 
>>> out = re.sub(r'EOD(.*?TrebsTito (\S+))', r'EOD \2\1', text, flags=re.S)
>>> print(out)
 
EOD R_Ti_174
PROFILE R_Ti_174 TYPE 1
SNAPPING PARAMETERS 5
5494510.000 1084246.625 0 14 2560.31 5855.34 5855.34 5855 I 2250 TrebsTito R_Ti_174
5494309.500 1084098.875 0 15 2476.59 5845.37 5845.37 5845 I 2250 TrebsTito R_Ti_174
5494300.500 1084402.750 1 14 2664.88 5852.30 5852.30 5852 I 2260 TrebsTito R_Ti_174
5494010.500 1084189.000 1 15 2476.50 5837.89 5837.89 5838 I 2260 TrebsTito R_Ti_174
 
EOD R_Ti_175
PROFILE R_Ti_175 TYPE 1
SNAPPING PARAMETERS 5
5494510.000 1084246.625 0 14 2560.31 5855.34 5855.34 5855 I 2250 TrebsTito R_Ti_175
5494309.500 1084098.875 0 15 2476.59 5845.37 5845.37 5845 I 2250 TrebsTito R_Ti_174
5494300.500 1084402.750 1 14 2664.88 5852.30 5852.30 5852 I 2260 TrebsTito R_Ti_174
5494010.500 1084189.000 1 15 2476.50 5837.89 5837.89 5838 I 2260 TrebsTito R_Ti_174
 
>>>
py.user.next
knoppix
Друг, можешь рассказать подробно, что происходит тут:
re.sub(r'EOD(.*?TrebsTito (\S+))', r'EOD \2\1', text, flags=re.S)
Спасибо!

1)
Это сырая строка
r''
Это регулярное выражение, записанное в сырой строке
r'EOD(.*?TrebsTito (\S+))'
Группа - это выражение в круглых скобках. Группы отсчитываются по левым скобкам.
\1 и \2 - это ссылки на группы по их номерам.

Когда регулярное выражение с чем-то совпадает, его группы заполняются текстом. Последующие ссылки на эти группы заменяются на тексты этих групп.

Пример:
>>> import re
>>> 
>>> match = re.search(r'(.)(.)(.)\1\2\3', 'abcabc')
>>> match.group(0)
'abcabc'
>>> match.groups()
('a', 'b', 'c')
>>>
Здесь регулярное выражение совпало со всей строкой, но группы заполнились только своими символами, которые использованы в регулярном выражении повторно через ссылки на группы.

2)
Это строка замены, записанная в сырой строке
r'EOD \2\1'
Строка замены связывается с регулярным выражением из строки поиска и берёт оттуда позицию совпадения и группы регулярного выражения. Потом заменяет собой совпадение.

flags=re.S
Флаги определяют режим поиска. Флаг S равен флагу DOTALL, который означает, что точка в регулярном выражении должна совпадать не только с любым символом, кроме символа перевода строки, но и с символом перевода строки.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB