У меня есть файл журнала, который выводится скриптом, файл журнала поворачивается ежедневно. Он будет содержать строки
Transfer started at timestamp
и
Transfer completed successfully at timestamp
несколько раз, так как упомянутая передача будет выполняться ежечасно. Временные метки ранее были созданы с помощью date.
Я хочу захватить последний экземпляр этих двух строк и все между ними в отдельный файл. Если начальная строка найдена в конце файла журнала, без следующей завершенной строки, я хочу захватить все до EOF и вывести сообщение об ошибке, чтобы сказать, что конечная строка не найдена.Я предполагаю, что мне нужно будет использовать sed или awk, но я действительно неопытен с ними. Я хочу использовать команду в сценарии bash и понять, что делает каждая часть, поэтому некоторые объяснения будут очень полезны.
Примерный фрагмент файла журнала:
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
...
[d8 ] Желаемый результат: 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
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)
Вы можете использовать массив awk с переключателем для буферизации последнего блока и напечатать текст ошибки, если переключатель все еще установлен в конце (это, по-моему, реализация awk @ python ответа anatoly_techtonik): [ ! d0]
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
Просто используйте 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")