Как получить конкретную информацию из двух строк текста и собрать имя файла из этого

В настоящее время я пишу сценарий для архивирования пары файлов журнала и хочу, чтобы они были объединены в один архив, который назван в соответствии с датой и временем первой и последней строк в одном из файлов журнала (то есть access.log).

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

рассматриваемые строки взяты из файла apache.log, который я просто мог получить с помощью head и tail:

Пример:

$ head -n1 /home/server/log/access.log.1 
84.1.11.243 - - [21/Jan/2017:14:53:49 +0000] "GET /index.php/2016/05/26/tutorial-how-to-install-ubuntu-and-other-debian-based-distributions-via-debootstrap/ HTTP/1.1" 200 18413 "https://www.google.hu/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"

$ tail -n1 /home/server/log/access.log.1 
71.3.17.120 - - [20/Dec/2017:16:17:50 +0000] "POST / HTTP/1.1" 200 27639 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; LCTE; rv:11.0) like Gecko"

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

Пример строки, которую я хотел бы использовать, но могу изменить ее в соответствии с результатами ответов:

tar -caf "backup-logfiles-$start-til-$end.tar.gz" access.log error.log ftp.log

Любое решение можно извлечь из этих значений в $start и $end.

4
задан 21 December 2017 в 23:27

2 ответа

Вот ужасно запутанная однострочная оболочка (используя формат даты, который вы упомянули в чате ):

$ name=$(printf 'backup-logfiles-%s-til-%s' $(date -d "$(head -n1 logfile | grep -oP '\[\K\S+' | sed 's|/| |g; s/:/ /')" +%Y-%m-%d-%H:%M:%S) $(date -d "$(tail -n1 logfile | grep -oP '\[\K\S+' | sed 's|/| |g; s/:/ /')" +%Y-%m-%d-%H:%M:%S))
$ echo $name
logfiles-2017-01-21-14:53:49-til-2017-12-20-16:17:50

Чтобы получить начальную и конечную переменные отдельно, выполните:

$ start=$(head -n1 logfile | grep -oP '\[\K\S+' | sed 's|/|-|g; s/:/ /')
$ end=$(tail -n1 logfile | grep -oP '\[\K\S+' | sed 's|/|-|g; s/:/ /')
$ echo "backup-logfiles-$start-til-$end.tar.gz"
backup-logfiles-21-Jan-2017 14:53:49-til-20-Dec-2017 16:17:50.tar.gz

Или, если вы хотите числовую дату:

$ start=$(date -d "$(head -n1 logfile | grep -oP '\[\K\S+' | sed 's|/|-|g; s/:/ /')" +%Y-%m-%d-%H:%M:%S)
$ end=$(date -d "$(tail -n1 logfile | grep -oP '\[\K\S+' | sed 's|/|-|g; s/:/ /')" +%Y-%m-%d-%H:%M:%S)
$ echo "backup-logfiles-$start-til-$end.tar.gz"
backup-logfiles-2017-01-21-14:53:49-til-2017-12-20-16:17:50.tar.gz
4
ответ дан 21 December 2017 в 23:27

Использование только sed, только для веселья победы в гольфе;)

name=$(sed -rn 's|/|-|g;s/.* \[([^ ]+) .*/\1/;1p;$p' file | sed 'N;s/\n/-til-/')
$ echo $name
21-Jan-2017:14:53:49-til-20-Dec-2017:16:17:50

Но если этот файл нужно передать tar, двоеточия могут вызвать проблемы:

An  archive  name  that has a colon in it specifies a file or device on a remote
machine.  The part before the colon is taken as the machine name or IP address,
and the part after it as the file or device pathname, e.g.:

    --file=remotehost:/dev/sr0

Вы можете обойти это, передав опцию:

--force-local
      Archive file is local even if it has a colon.

Но вот команда, которая заменяет двоеточия большим количеством дефисов:

name=$(sed -rn 's|[/:]|-|g;s/.* \[([^ ]+) .*/\1/;1p;$p' file | sed 'N;s/\n/-til-/')

Вместо класса символов мы могли бы использовать чередование и сохранить байт:)

name=$(sed -rn 's#/|:#-#g;s/.* \[([^ ]+) .*/\1/;1p;$p' file | sed 'N;s/\n/-til-/')

Примечания

  • -r использовать ERE
  • -n ничего не печатайте, пока мы не попросим
  • s|/|-|g заменить все символы / на - (потому что у нас не может быть имени файла с /)
  • s|[/:]|-|g заменить символы / и : дефисами везде.
  • s#/|:#-#g заменить / или : на - везде
  • ; отдельные команды sed
  • s/.* \[([^ ]+) .*/\1/ записывать дату и время между квадратные скобки (от первого [ до первого пробела).
  • 1p;$p печатать только первую строку и последнюю строку
  • | направлять ее в другую sed (тьфу!)
  • N читать обе строки в шаблон пространство ...
  • s/\n/-til-/ ... так что мы можем заменить новую строку на -til-
4
ответ дан 21 December 2017 в 23:27

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

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