Друзья, нужна помощь.
есть задача найти в файле искомое значение(в виде даты - 2021-05-05 06:00) и если такой строки нет, то искать ближайшее занчение.
я понимаю как проверить наличие строки в файле - grep -q "${start}" myfile.txt
я понимаю как из даты вычесть необходимое мне время - date --date=''$start' 1 minutes ago' '+%Y-%m-%d %H:%M'
но я никак не пойму как мне все это загнать в цикл.
Т.е. должно выглядеть типа:
#!/bin/bash
#вводим значение
read start
#дальше идет цикл, который
#проверят наличие строки и если она есть пишет ок
# если такой строки нет, вычитает из из $start одну минуту и проверяет наличие получившегося значения в файле,
если таковое значение есть, выдает переменную с таким значением и печатает содержимое этой переменной.
# если такого значения снова не оказалось, то вычитает еще одну минуту и снова проверяет и так до тех пор пока не найдет совпадение.
циклы в bash (Друзья, нужна помощь.)
Модератор: Bizdelnick
-
- Модератор
- Сообщения: 21243
- Статус: nulla salus bello
- ОС: Debian GNU/Linux
Re: циклы в bash
Как-то Вы не с той стороны к задаче подошли. Не надо тыщу раз проходить по файлу, инкрементируя искомое время. Я ведь правильно понимаю, что это лог, в котором записи заведомо упорядочены по времени? Перебирайте в цикле строки по одной (while read …), пока не дойдёте до той, в которой время не меньше искомого. Для сравнения преобразуйте время в формат %s.
Если это не лог, и порядок следования строк произвольный, решение будет таким же, просто сперва надо будет отсортировать строки по возрастанию времени.
Если это не лог, и порядок следования строк произвольный, решение будет таким же, просто сперва надо будет отсортировать строки по возрастанию времени.
Добавлено (18:30):
Если имеется в виду ближайшее значение как до, так и после искомого времени, то надо сохранять одну предыдущую прочитанную строку и при нахождении той, которая содержит время после искомого, проверять, какая из двух ближе.
Пишите правильно:
в консоли вку́пе (с чем-либо) в общем вообще | в течение (часа) новичок нюанс по умолчанию | приемлемо проблема пробовать трафик |
-
- Сообщения: 4
- ОС: ubuntu
Re: циклы в bash
да это лог.
Идея ваша звучит разумнее, но мне все равно не хватает опыта, чтобы это реализовать.
В любом случае, спасибо большое. Буду думать в этом направлении.
Идея ваша звучит разумнее, но мне все равно не хватает опыта, чтобы это реализовать.
В любом случае, спасибо большое. Буду думать в этом направлении.
-
- Модератор
- Сообщения: 21243
- Статус: nulla salus bello
- ОС: Debian GNU/Linux
Re: циклы в bash
А в чём проблема, собственно? Задаёте референсное время
Код: Выделить всё
read TIME
TIME=$( date --date="$TIME" +%s )
Код: Выделить всё
while read line; do
# здесь проверка времени
done <myfile.txt
Код: Выделить всё
ltime=$( echo "$line" | sed -En 's/(^\d{4}-\d{2}-\d{2} \d{2}:\d{2}).*/\1/p' ) # считается, что время в начале строки в указанном Вами формате
ltime=$( date --date="$ltime" +%s ) # перевод времени в секунды эпохи
if [ "$ltime" -ge "$TIME" ]; then
echo "$line"
break
fi
Добавлено (20:34):
Да, надо ещё на всякий случай проверять, что $ltime не пустая. А то date вернёт текущее время.Пишите правильно:
в консоли вку́пе (с чем-либо) в общем вообще | в течение (часа) новичок нюанс по умолчанию | приемлемо проблема пробовать трафик |
-
- Сообщения: 4
- ОС: ubuntu
Re: циклы в bash
пошел немного другим путем. Коряво конечно и долго, но работает. Так что оставлю здесь, вдруг кому пригодится))
Добавлено (17:26):
Shell
#!/bin/bash
#скрипт заускаем так - "./script.sh 1" - в таком случае лог выведется за последние 24, т.к. все остальные
#переменные будут дефолтными=0. Если запустить "./script.sh 0 12 0 0 1 0" - выдаст за посление 12 часов, без учета последнего часа,
#т.е. если сейчас 12 часов дня, то получим лог в период с 00 часов и до 11. И т.д.
start=$(date --date=''${1:-0}' day ago '${2:-0}' hours ago '${3:-0}' minutes ago' '+%b %_d %H:%M')
end=$(date --date=''${4:-0}' day ago '${5:-0}' hours ago '${6:-0}' minutes ago' '+%b %_d %H:%M')
echo 'Хотим за этот диапазон' $start '-' $end
#переводим в секунды
starts=$(date -d "$start" +%s)
ends=$(date -d "$end" +%s)
#Формат даты в файле такой - May 9 13:23:27, поэтому выводим 1,2,3-ий столбец и переводим в секунды. Дальше ищем меньше или ровно наших вводных
starts=$(awk '{print $1,$2,$3}' /var/log/syslog | date -f - +"%s" | awk '$1<='$starts'' | tail -1)
#Преобразуем снова в дату, в такой же формат как и в файле
start=$(date -d @"$starts" '+%b %_d %H:%M')
ends=$(awk '{print $1,$2,$3}' /var/log/syslog | date -f - +"%s" | awk '$1<='$ends'' | tail -1)
end=$(date -d @"$ends" '+%b %_d %H:%M')
echo 'Есть только за этот диапазон' $start '-' $end
#Печатаем все от первого до второго вхождения и грепаем по условию
sed -n "/${start}/,/${end}/p" /var/log/syslog | grep 'error'