Уведомления

Группа в Telegram: @pythonsu

#1 Сен. 22, 2015 08:31:44

knoppix
Зарегистрирован: 2015-09-22
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

Друзья, я не настоящий сварщик, но у меня есть стремление учиться. Есть задача, которую я могу решить на 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. Я не прошу эту задачу за меня решать, просто скажите так, на словах, как это сделать красиво?





Отредактировано knoppix (Сен. 22, 2015 09:57:13)

Офлайн

#2 Сен. 22, 2015 09:15:54

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10016
Репутация: +  857  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

Используй теги кода.
Приведи пример входного блока и выходного блока, который получается.



Офлайн

#3 Сен. 22, 2015 10:12:37

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

Если файл маленький то:

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)



Отредактировано doza_and (Сен. 22, 2015 10:27:55)

Офлайн

#4 Сен. 22, 2015 10:20:37

knoppix
Зарегистрирован: 2015-09-22
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

doza_and, спасибо, это работает.
Можешь объяснить что происходит в 3,4 строчках кода?
И что будет, если файл большой?

Отредактировано knoppix (Сен. 22, 2015 10:21:49)

Офлайн

#5 Сен. 22, 2015 10:32:28

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

knoppix
Можешь объяснить что происходит в 3,4 строчках кода?
Во второй задается шаблон поиска при помощи регулярных выражений. При этом Флаги выставляем так, чтобы регулярное выражение работало не построчно а во всем тексте. Это чтобы его действие продлилось на несколько строк и можно было выцепить результат из следующих строчек
В строке 4 происходит замена с использованием этого шаблона сразу для всего файла.
Я привел второй подход. можно сказать более традиционный.



Офлайн

#6 Сен. 22, 2015 10:39:43

knoppix
Зарегистрирован: 2015-09-22
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

doza_and
Непонятно почему из 3 строчки. Во второй тоже есть.

По условию задачи, нужно брать из третьей строчки. Спасибо тебе!

Офлайн

#7 Сен. 22, 2015 11:29:11

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10016
Репутация: +  857  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

>>> 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
 
>>>



Офлайн

#8 Сен. 23, 2015 03:47:49

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10016
Репутация: +  857  -
Профиль   Отправить e-mail  

Правка текстового файла поблоково.

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



Отредактировано py.user.next (Сен. 23, 2015 03:55:27)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version