Форум сайта python.su
Друзья, я только начинаю изучать язык, у меня такой вопрос к опытным людям.
Есть файл, примерно вот с таким содержимым:
<code=“524426745”>
<id=1>
<id=2>
</code=“524426745”>
<code=“524426442”>
<id=1>
<id=2>
</code=“524422442”>
Задача такова, надо найти начало блока по коду то есть: <code=“524426745”>, и читать строки в переменную или в файл до тех пор пока не дойдем до </code=“524426745”>
Я набросал такой код:
f = open('russianpost.log', 'r') for line in f.xreadlines(): if '524426745' in line: print line f.close()
Офлайн
>>> import re >>> >>> text = """ ... ... <code="524426745"> ... <id=1> ... <id=2> ... </code="524426745"> ... ... <code="524426442"> ... <id=3> ... <id=4> ... </code="524422442"> ... ... <code="524426443"> ... <id=5> ... <id=6> ... </code="524422443"> ... ... """ >>> >>> def split_records(s): ... pat = r'<code.*?</code.*?>' ... out = re.findall(pat, s, re.DOTALL) ... return out ... >>> def parse_record(s): ... pat = r'<code="(.*)">(.*)</code.*>' ... match = re.search(pat, s, re.DOTALL) ... if match is not None: ... number = match.group(1) ... content = parse_content(match.group(2)) ... return (number, content) ... else: ... return None ... >>> def parse_content(s): ... pat = r'<id=(.*)>' ... out = tuple(re.findall(pat, s)) ... return out ... >>> records = split_records(text) >>> records ['<code="524426745">\n<id=1>\n<id=2>\n</code="524426745">', '<code="524426442">\n<id=3>\n<id=4>\n</code="524422442">', '<code="524426443">\n<id=5>\n<id=6>\n</code="524422443">'] >>> >>> out = list(map(parse_record, records)) >>> out [('524426745', ('1', '2')), ('524426442', ('3', '4')), ('524426443', ('5', '6'))] >>>
Отредактировано py.user.next (Фев. 25, 2017 03:06:01)
Офлайн
Честно сказать я не совсем понял решение. Если честно. Как я это вижу? Открывается файл, ищем весь текст до первого вхождения (<code=“524426745”>), находим, значит выводим строку, раз строка найдена, выводим все остальные строки до тех пор, пока не встретим второе вхождение (</code=“524426745”>) .
Я думал искать по следующему, первое вхождение (524426745), потом все строки, второе вхождение (</code).
Вот как-то так…
Офлайн
Вот, наверное, то, как видите Вы
with open('2.txt', 'r') as f: start = False for line in f: if '<code="524426745">' in line: start = True if start: print(line) if '</code="524426745">' in line: start = False
Отредактировано Romissevd (Фев. 24, 2017 17:03:29)
Офлайн
Да! Это именно то, что мне было нужно… теперь буду разбираться. А почему вы считаете что это говнокод? Ведь это работает. Может быть с точки зрения “чистого” программирования это и выглядит нагромождением, но ведь работает . При том делает как раз то, что мне было нужно…
Офлайн
appolo440Ты когда файл прочитаешь через f.read(), получишь текст весь, который подашь в функцию, которая разделяет его на записи. И потом, когда уже разделишь его на записи, ты возьмёшь первую из них.
Честно сказать я не совсем понял решение. Если честно. Как я это вижу? Открывается файл, ищем весь текст до первого вхождения (<code=“524426745”>), находим, значит выводим строку, раз строка найдена, выводим все остальные строки до тех пор, пока не встретим второе вхождение (</code=“524426745”>) .
appolo440У Romissevd оно берёт только определённую запись (с определённым номером) и больше ничего не делает с ней. Если тебе понадобится запись с другим номером, то этот код ты уже не применишь, потому что в нём номер зашит (надо менять код). Если код надо менять, то он фиговым считается, так как хороший код параметризован - ты просто меняешь вводный параметр и код без каких-либо изменений применим к другим записям. Чем больше код параметризован, тем он лучше. В данном случае код должен быть параметризован ещё и по источнику данных. Но у него в код зашито ещё и то, что данные берутся только из файла. Значит, если они придут по сети (через соединение) или по почте, то ты не сможешь эти данные сразу подать в код, потому что он требует именно файл, сначала ты должен будешь сохранять данные на диск, а потом этот файл подавать, но данные на диск может быть запрещено сохранять или на нём может закончиться место. В хорошем коде данные принято передавать прямо из оперативной памяти (она быстрее работает, чем диски, и меньше изнашивается). Ну, и самая главная параметризация, которая у него отсутствует, - это номер записи по счёту. Он не может выбрать третью запись из пяти, например, и с ней работать, потому что он вообще их не считает. Он не может выбрать 3, 10 и 115 записи, потому что сами записи в его потоке не разделяются.
Может быть с точки зрения “чистого” программирования это и выглядит нагромождением, но ведь работает .
<code="524426745">
<id=1>
<id=2>
</code="524426745">
('524426745', ('1', '2'))
Отредактировано py.user.next (Фев. 26, 2017 01:55:23)
Офлайн
Спасибо всем друзья!
С вашей помощью привел свой код до следующего состояния:
В файл in.log записываются коды вхождений.
Вначале файла задаю переменные и далее отрабатываю:
in_log = 'in.log' out_log = 'out.log' def parse_line(input_file, start_string, end_string): start_parse = False f = open (input_file, 'r') for line in f.xreadlines(): if start_string in line: start_parse = True if start_parse: print line, if end_string in line: start_parse = False f.close() def search_line(): f = open (in_log, 'r') for lines in f.xreadlines(): line = lines.split() parse_line(out_log, line[0], '</') f.close() search_line()
Офлайн
appolo440:) Добавлю свою ложку дегтя.
привел свой код до следующего состояния:
import re def cvt(fnd): if fnd.group(1)=="code": return fnd.group(2) +" :\n" if fnd.group(1)=="id": return " - " + fnd.group(2) return "" with open("a.xml","r") as f_in, open("a.yaml","w") as f_out: for i in f_in: f_out.write(re.sub("<(.+)=(.+)>",cvt,i))
import yaml with open("a.yaml","r") as f: d=yaml.load(f)
Отредактировано doza_and (Фев. 25, 2017 12:32:17)
Офлайн
Дело в том, что это не .xml формат. Я привел это исключительно ради примера, в файле в котором будет производится поиск куча всего, это stdout от java приложения, туда пишется все что только можно, включая нужную мне информацию. Но спасибо вам за время и внимание! )
Офлайн
appolo440А я и не предполагал что это xml, никакие xml парсеры не использовал. Как раз когда в файле куча непотребного мусора фильтры проще всего и писать. Зачастую вы при этом разбираете пару вам нужных конструкций из сотен, поэтому код сильно сокращается. Но самый лучший способ это залезть в java код и изменить сохранение так чтобы не было проблем с чтением.
Дело в том, что это не .xml формат.
Офлайн