Как напечатать строки X строк до правильного оператора if - PullRequest
0 голосов
/ 25 апреля 2018

Я новичок в Python, и у меня есть только кусочные знания о том, что я нашел на многочисленных веб-страницах.

При этом я пытаюсь найти в файле (~ 10 тыс. Строк) набор критериев, подобный фильтру, который я написал, и затем я хочу напечатать строки, которые соответствуют критериям, и строку, которая является X количество строк перед ним.

Я создал следующий сценарий, чтобы открывать указанный файл, итерацию построчно и печатать строку, соответствующую критериям фильтра, в выходной файл, однако я не знаю, как включить это в текущий сценарий.

import os

output_file = 'Output.txt'
filename = 'BigFile.txt'                 

numLines = 0
numWords = 0
numChrs = 0
numMes = 0

f1 = open(output_file, 'w')
print 'Output File has been Opened'

with open(filename, 'r') as file:
   for line in file:
      wordsList = line.split()
      numLines += 1
      numWords += len(wordsList)
      numChrs += len(line)

      if "X" in line and "Y" not in line and "Z" in line:
          numMes += 1
          print >>f1, line
          print 'Object found and Catalogued in Output.txt'                          

print "Lines: %i\nWords: %i\nCharacters: %i" % (numLines, numWords, numChrs)
print >>f1, "Lines: %i\nWords: %i\nCharacters: %i" % (numLines, numWords, numChrs)

print "There are a total of %i thing in this file" % (numMes)
print >>f1, "There are a total of %i things in this file" % (numMes)

f1.close()

print 'Output Files have been Closed'

Моим первым предположением было использование line.enumeration, но я не думаю, что могу просто указать что-то вроде lines - 5, чтобы напечатать строку, равную 5 до lines:

lines = f1.enumeration()
if "blah blah" in line and "so so" not in line:
    print >>f1, lines
    print >>f1, [lines - 5]

Лучшая часть еще впереди, потому что мне нужно взять файл Output.txt и сравнить с другим файлом, чтобы вывести критерии соответствия в обоих файлах ... но по одному шагу за раз, верно?

-Также не стесняйтесь добавлять в «правильную» технику ... Я уверен, что этот сценарий можно написать лучше, поэтому, пожалуйста, расскажите мне обо всем, что я делаю неправильно.

Заранее спасибо за любую помощь!


UPDATE: Успешно внедрили это исправление благодаря помощи ниже:

import os

output_file = 'Output.txt'
filename = 'BigFile.txt'                 

numLines = 0
numWords = 0
numChrs = 0

numMulMes = 0

last5 = []

f1 = open(output_file, 'w')
print 'Output Files have been Opened'

with open(filename, 'r') as file:
    for line in file:
        wordsList = line.split()
        numLines += 1
        numWords += len(wordsList)
        numChrs += len(line)
        last5[:] = last5[-5:]+[line] 
        if "X" in line and "Y" not in line and "Z" not in line:
            del last5[1:5]           ###the missing piece of the puzzle!
            numMulMes += 1
            print >>f1, last5
            print 'Object found and Catalogued in Output.txt'

print "Lines: %i\nWords: %i\nCharacters: %i" % (numLines, numWords, numChrs)
print >>f1, "Lines: %i\nWords: %i\nCharacters: %i" % (numLines, numWords, numChrs)

print "There are a total of %i messages in this file" % (numMulMes)
print >>f1, "There are a total of %i messages in this file" % (numMulMes)

f1.close()
f3.close()

print 'Output Files have been Closed'

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

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

Ответы [ 4 ]

0 голосов
/ 25 апреля 2018

Поскольку я упоминал об этом в комментариях , здесь описывается, как сделать то же самое на * nix-машине, используя grep элемент управления контекстной строкой функции.

Сначала предположим, что у вас есть следующий текстовый файл test.txt:

zero line
one line
two line
three line
four line 
five line 
six line
seven line 
eight line

Если вы хотите получить N строк до начала матча, вы можете использовать опцию -B. Например, для 5 строк перед "six":

$ grep -B 5 six test.txt 
one line
two line
three line
four line 
five line 
six line

Существует также опция -A, которую можно использовать для получения N строк после матча и -C, которую можно использовать для получения N строк до и после.

0 голосов
/ 25 апреля 2018

Вместо записи в файл я вывожу материал в словарь. Как только весь файл обработан, словарь сводных данных выгружается в файл в виде json. Использование тестового файла Артнера.

import os
import json

output_file = 'Output.txt'
filename = 'BigFile.txt'                 

#initiate output container
outDict = {}
for fields in ['numLines', 'numWords', 'numChrs', 'numMes']:
    outDict[fields] = 0

outDict['lineNum'] = []    

with open(filename, 'r') as file:
    for line in file:
      wordsList = line.strip().split("\s")
      outDict['numLines'] += 1
      outDict['numWords'] += len(wordsList)
      outDict['numChrs'] += len(line)

      #find items in the line
      if "t" in line:
          outDict['numMes'] += 1
          #save line number
          outDict['lineNum'].append(outDict['numLines']) 
          #save line content
          outDict['lineList'].append(line)

#record output          
with open(output_file, 'w') as f1:
    f1.write(json.dumps(outDict))    

##print lines of desire
#x number of lines before
x=5    
with open(filename, 'r') as file:
    for i, line in enumerate(file):
        #iterate over line numbers for which condition is met
        for j in range(0,len(outDict['lineNum'])):
            #if line number is between found line num and line num minus x, print
            if (outDict['lineNum'][j]-x) <= i <= outDict['lineNum'][j]:
                print(line)
0 голосов
/ 25 апреля 2018

Здесь то же решение, что и @PatricArtner, но с кольцевым буфером. Это может (или нет, я не проверял) работать быстрее с большими файлами. Идея довольно проста: мы можем создать список с требуемым размером (количество строк, которое вы должны сохранить) и счетчиком текущей позиции записи cnt. Для каждой новой строки мы должны увеличить cnt на единицу и сделать по модулю размер нашего буфера. Поэтому cnt зацикливается внутри списка. Например, если размер списка 5 cnt = (cnt+1)%5, то получится 0 1 2 3 4 0 1 2 и так далее. Каждый шаг cnt будет указывать на самые старые данные в нашем списке, которые будут заменены новыми данными. Пример реализации ниже.

t = """"zero line
six line - surprize 
one line
two line
three line
four line 
five line 
six line
seven line 
eight line
""" 


last5 = [None,None,None,None,None]
cnt = 0
for l in t.split("\n"):
  last5[cnt]=l
  if 'six' in l:
    print last5[(cnt+1)%5]
    print last5[(cnt+2)%5]
    print last5[(cnt+3)%5]
    print last5[(cnt+4)%5]
    print last5[(cnt+0)%5]
    print
  cnt = (cnt+1)%5

Вывод довольно прост:

None
None
None
"zero line
six line - surprize 

two line
three line
four line 
five line 
six line

ПРИМЕЧАНИЕ: Если вы читаете из файла, и файл довольно большой, и строки, которые вам нужно сохранить, огромны (например, последовательности генов), и ваше состояние не срабатывает так часто, быть умным, не хранить строки в памяти. Создайте список позиций в файле, где начинаются последние строки и перечитайте их, если вам нужно. Ниже приведен пример того, как сделать это очень быстро ...

from numpy import random as rnd

print "Creating the file ...."
DNA=["G","C","T","A"]
with open("bigdatafile","w") as fd:
    for i in xrange(5000):
        fd.write("".join([ DNA[rnd.randint(4)] for x in xrange(2000)])+"\n")
print "DONE"
print
print "SEARCHING GGGGGGGGGGG"
last5, cnt = [0,0,0,0,0], 1
with open("bigdatafile","r") as fd:
    for i,l in enumerate(fd.readlines()):
        last5[cnt] = last5[(cnt+4)%5]+len(l)
        if "GGGGGGGGGGG" in l:
            print "FIND!"
            fd.seek(last5[(cnt+1)%5])
            print fd.read(last5[cnt]-last5[(cnt+1)%5])
        cnt = (cnt+1)%5
0 голосов
/ 25 апреля 2018

Вы решили большинство вещей самостоятельно (считая слова, строки, белье и т. Д.) - Вы можете просто запомнить последние n строк, просматривая свой файл.

Пример:

t = """"zero line
one line
two line
three line
four line 
five line 
six line
seven line 
eight line
""" 

last5 = [] # memory cell
for l in t.split("\n"):  # similar to your for line in file: 
    last5[:] = last5[-4:]+[l] # keep last 4 and add current line, inplace list mod 

    if "six" in l:
        print last5

Вы также можете посмотреть на deque и указать максимальную длину (вам необходимо импортировать ее)

from collections import deque

last5 = deque(maxlen=5)
for l in t.split("\n"): 
    last5.append(l) # will automatically only keep 5 (maxlen)

    if "six" in l:
        print last5

Выход:

 # list version
 ['two line', 'three line', 'four line ', 'five line ', 'six line'] 

 # deque version
 deque(['two line', 'three line', 'four line ', 'five line ', 'six line'], maxlen=5) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...