Как получить строки между двумя строками из файла, но только последнее вхождение?

У меня есть файл журнала, который производится сценарием, файл журнала ежедневно поворачивается. Это будет содержать строки

Transfer started at timestamp 

и

Transfer completed successfully at timestamp

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

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

Я предполагаю, что должен буду использовать sed или awk но действительно неопытно с ними. Я хочу использовать команду в сценарии удара и понять то, что делает каждая часть, таким образом, некоторое объяснение было бы очень полезно.

Блок в качестве примера файла журнала:

ERROR - Second tech sync failed with rsync error code 255 at Fri May 27 13:50:4$
--------------------------------------------------------------------
After_sync script completed successfully with no errors.
Main script finished at Fri May 27 13:50:43 BST 2016 with PID of 18808.
--------------------------------------------------------------------
Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.
37 approvals pending.
Transfer completed successfully at Fri May 27 14:05:16 BST 2016
--------------------------------------------------------------------
Local repository verification started at Fri May 27 14:35:02 BST 2016
...

Желаемый вывод:

Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.
37 approvals pending.
Transfer completed successfully at Fri May 27 14:05:16 BST 2016

Однако, если файл журнала был похож на это:

ERROR - Second tech sync failed with rsync error code 255 at Fri May 27 13:50:4$
--------------------------------------------------------------------
After_sync script completed successfully with no errors.
Main script finished at Fri May 27 13:50:43 BST 2016 with PID of 18808.
--------------------------------------------------------------------
Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.

Я хотел бы произвести:

Transfer started at Fri May 27 13:50:45 BST 2016
Logs transferred successfully.
Images transferred successfully.
Hashes transferred successfully.
ERROR: transfer not complete by end of log file
4
задан 20 June 2016 в 12:33

4 ответа

Когда я слышу, что "Хочу сделать X с последним что-то в файле", я думаю:

  • инвертируйте файл
  • сделайте X с первым что-то в файле
  • инвертируйте вывод X

В коде:

tac logfile | awk '
    BEGIN {text = "ERROR: transfer not complete by end of log file"}
    /^Transfer completed successfully/ {text = ""}
    {text = text ORS $0}
    /^Transfer started at / {print text; exit}
' | tac

Так как мы читаем файл журнала с самого начала, я запускаю с предположения, что передача не завершается. Если я вижу, что "передача завершила" сообщение, мы можем вывести то, что мы получили до сих пор. Мы сохраняем каждую строку. Когда мы видим, что "передача запустила" строку, мы знаем, что видели всю последнюю передачу в файле: распечатайте (обратный) полученный текст и выйдите из awk.

2
ответ дан 1 December 2019 в 09:33

Python все вещи, но позволяют регулярным выражениям сделать работу для Вас!

Вставьте сценарий ниже в любой файл, например. logfilter.py и сделайте это исполняемым файлом с помощью команды chmod +x logfilter.py.

Затем можно выполнить его как это, предположив, что это расположено в текущем каталоге:

./logfilter.py logfile.txt

Это заставит его обработать файл logfile.txt.

Однако, если Вы не передадите его никакие параметры командной строки, то это будет ожидать данных по стандартному входу. Это означает, что можно также передать данные по каналу в него. Следующий пример обрабатывает данные от буфера обмена (потребности xsel установленный для доступа к буферу обмена):

xsel -ob | ./logfilter.py

Сценарий:

#! /usr/bin/env python3

p_start = r'^Transfer started at .*?$'
p_end   = r'^Transfer completed successfully at .*?$'

error_no_match = 'ERROR: no match found'
error_no_end   = 'ERROR: transfer not complete by end of log file'

pattern = r'{p0}(?!.*{p0})(?:.*?{p1}|.*)'.format(p0=p_start, p1=p_end)

import sys, re
if len(sys.argv) > 1:
    with open(sys.argv[1]) as f:
        text = f.read()
else:
    text = sys.stdin.read()

matches = re.findall(pattern, text, re.DOTALL | re.MULTILINE)
if matches:
    last_match = matches[-1]
    print(last_match)
    if not re.search(p_end, last_match, re.DOTALL | re.MULTILINE):
        print(error_no_end)
else:
    print(error_no_match)
1
ответ дан 1 December 2019 в 09:33

Вы могли использовать массив awk с переключателем, чтобы буферизовать последний блок и распечатать текст ошибки, если переключатель все еще установлен в конце (это - по существу awk реализация ответа Python @anatoly_techtonik, я думаю):

awk '
  BEGIN{PROCINFO["sorted_in"]="@ind_num_asc"}

  /Transfer started/ {inblock=1; delete a;}
  /Transfer completed/ {a[FNR]=$0; inblock=0;}

  inblock == 1 {a[FNR]=$0}

  END {
    for (i in a) print a[i]; 
    if (inblock) 
      print "ERROR: transfer not complete by end of log file"
  }
' logfile
1
ответ дан 1 December 2019 в 09:33

Просто используйте Python. У меня действительно нет времени, но я запустил бы с этого:

#!/usr/bin/env python

start = "Transfer started at"
end = "Transfer completed successfully"
buffer = ""
log = False

for line in open('logfile.log'):
  if line.startswith(start):
    buffer = line
    log = True
  elif line.startswith(end):
    buffer += line
    log = False
  elif log:
    buffer += line

open('output.log', 'w').write(buffer)

if log == True:
  print("End string was not found")
1
ответ дан 1 December 2019 в 09:33

Другие вопросы по тегам:

Похожие вопросы: