Как разделить один файл на два с помощью Python? [закрыто]

У меня есть файл, содержащий несколько строк кода, а затем шаблон строки. Мне нужно написать все до строки, содержащей шаблон строки в файле один и все после шаблона строки в файле два:

например (Файл-контент)

codeline 1 codeline 2 string pattern codeline 3

Выходными данными должен быть файл один с кодовой строкой 1, кодовой строкой 2 и файл два с кодовой строкой 3.

Я знаком с написанием файлов, но, к сожалению, я не знаю, как определить содержимое до и после строкового шаблона.

 tabchas13 июн. 2012 г., 20:19
Не могли бы вы привести пример используемого строкового шаблона и кодовой строки? - Это также файл .csv или обычный файл .txt?

Ответы на вопрос(7)

with open('data.txt') as inf, open('out1.txt','w') as of1, open('out2.txt','w') as of2:
    outf = of1
    for line in inf:
        if 'string pattern' in line:
            outf = of2
            continue  # prevent output of the line with "string pattern" 
        outf.write(line)

так как работает построчно. Предполагаетstring pattern происходит только один раз во входном файле. мне нравитсяstr.partition() подходить лучшеif весь файл может поместиться в память (что не может быть проблемой)

С помощьюwith гарантирует, что файлы будут автоматически закрыты, когда вы закончите, или возникнет исключение.

 13 июн. 2012 г., 20:31
Закрыть, но я верю, что ваш код приведет к «строковому шаблону» появляется вoutf2когда в вопросе указано, что «строковая структура» должен исчезнуть с выхода. В этом случае просто добавьтеcontinue как следующая строка послеoutf = outf2 и это должно работать.
 13 июн. 2012 г., 20:33
@Robru я упомянул об использованииcontinue сделатьstring pattern исчезнуть, но, думаю, мне следовало бы прочитать вопрос более внимательно :-) .. Я обновлю свое решение, спасибо.

Л. & APOS; s но используетitertools потому что это весело.

 dont_break = lambda l: l.strip() != 'string_pattern'

 with open('input') as source:
     with open('out_1', 'w') as out1:
         out1.writelines(itertools.takewhile(dont_break, source))
     with open('out_2', 'w') as out2:
         out2.writelines(source)

Вы можете заменить функцию dont_break регулярным выражением или чем-то еще, если это необходимо.

 13 июн. 2012 г., 20:31
+1 для удовольствия.
 13 июн. 2012 г., 20:30
Это, вероятно, лучшее решение для файлов, которые не помещаются в памяти. Itertools означает, что циклы выполняются на C-стороне, что означает, что они будут быстрее (что может иметь значение, учитывая большое количество строк, которые можно ожидать, если память имеет значение). Я отмечу, что если вы собираетесь определять лямбду отдельно, как это, Вы могли бы также использоватьdef заявление.

with open('infile') as fp, open('of1','w') as of1, open('of2','w') as of2:
    of1.writelines(iter(fp.readline, sentinel))
    of2.writelines(fp)
 14 июн. 2012 г., 18:31
Хорошая точка зрения! Я всегда забываю об этой формеiter, Конечно, это работает только для точно известных часовых, а не для регулярных выражений или чего-то подобного.

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

inp = open('inputfile')
out = open('outfile1', 'w')
for line in inp:
  if line == "Sentinel text\n":
    out.close()
    out = open('outfile2', 'w')
  else:
    out.write(line)
out.close()
inp.close()
 13 июн. 2012 г., 20:28
Использоватьwith заявление, где открытие файлов.

Вам нужно что-то вроде:

def test_pattern(x):
    if x.startswith('abc'): # replace this with some exact test
        return True
    return False

found = False
out = open('outfile1', 'w')
for line in open('inputfile'):
    if not found and test_pattern(line):
        found = True
        out.close()
        out = open('outfile2', 'w')
    out.write(line)
out.close()

замените строку на начальные с тестом, который работает с вашим шаблоном (при необходимости используйте сопоставление с шаблоном из re, но все, что найдет разделительную линию, подойдет).

 13 июн. 2012 г., 20:28
Использоватьwith заявление, где открытие файлов.
 13 июн. 2012 г., 20:37
@Lattyware: with - это хорошо, но неуместно, так как это относительно новое дополнение к Python, и мы не знаем, какую версию Python использует dom_frank.
 13 июн. 2012 г., 20:38
@Anthon Никто, кто только изучает Python, не будет использовать что-либо до 2.5; если ОП использует 2.5, то ему просто нужно добавитьfrom __future__ import with_statement.
 13 июн. 2012 г., 20:40
@Anthon Только то, что что-то новое, не означает, что его следует избегать, кроме того, как говорит Дугал, это отнюдь не новая функция. Это стандарт, и каждый (как должен) использует его. Я считаю, что любой новый код не использует его как неправильный - он приводит к потенциальным ошибкам без причины и снижает читабельность.
 13 июн. 2012 г., 20:35
@Sven: спасибо, что заметили опечатки. ИМХО, неподходящий, неуместен, если вы еще не знаете, как именно тестировать, это был просто легко расширяемый пример с провалом в том, чтобы быть ложным. Если тест становится многострочным с другими операторами if, например, найдите первые 2 символа, а затем разделите их на «& apos; |»; и осмотрите следующие два символа, тогда это легче адаптировать.

Наивный пример (который не загружает файл в память, подобную Sven's):

with open('file', 'r') as r:
    with open('file1', 'w') as f:
        for line in r:
            if line == 'string pattern\n':
                break
            f.write(line)
    with open('file2', 'w') as f:
        for line in r:
            f.write(line)

Это предполагает, что'string pattern' происходит один раз во входном файле.

Если шаблон не является фиксированной строкой, вы можете использоватьre модуль.

 13 июн. 2012 г., 20:28
Использоватьwith заявление, где открытие файлов.
 13 июн. 2012 г., 20:47
Вы, кажется, обиделись, если вы знаете, что это лучшая идея, то почему бы не использовать ее? Если вы не хотите давать код без просмотра кода, спросите код у спрашивающего, не дайте ответ, который работает, но имеет скрытые потенциальные ошибки - которые вредны для всех (например, людей, которые могут столкнуться с этим вопросом). ищу ответ позже). Я даю предложение улучшить ответ, который соответствует принципу работы SO. Это не нападение на вас, это попытка улучшить ресурс.
 13 июн. 2012 г., 20:30
@ Lattyware этоnaive пример :) Кроме того, в этом конкретном случае адаптировать код к использованию сложнее, чем обычноwith.
 13 июн. 2012 г., 20:56
Комментарии не показывают это достаточно ясно. В духе SO я сделал редактирование самостоятельно (и исправил еще одну незначительную ошибку - шаблону нужна новая строка для работы).
 13 июн. 2012 г., 20:34
А также?with это лучшая практика Нет причин не использовать его. Идея о том, что ее трудно изменить, просто не соответствует действительности, поскольку ее проще использовать и она обеспечивает закрытие файлов, даже в исключительных ситуациях, - то, что ваш код даже не пытается в данный момент.
Решение Вопроса

Если входной файл помещается в память, самое простое решение - использоватьstr.partition():

with open("inputfile") as f:
    contents1, sentinel, contents2 = f.read().partition("Sentinel text\n")
with open("outputfile1", "w") as f:
    f.write(contents1)
with open("outputfile2", "w") as f:
    f.write(contents2)

Это предполагает, что вы знаете точный текст строки, разделяющей две части.

 13 июн. 2012 г., 20:35
+1. Это действительно хорошее, чистое, удобочитаемое решение, если оно умещается в памяти.
 13 июн. 2012 г., 20:43
+1 мой любимый, предпочитаю его моему собственному решению, если учесть то же самое в отношении уместности в памяти

Ваш ответ на вопрос