циклы в bash (Друзья, нужна помощь.)

Для новичков как вообще в Linux, так и в конкретной теме, к которой относится вопрос.

Модератор: Bizdelnick

kosstya
Сообщения: 4
ОС: ubuntu

циклы в bash

Сообщение kosstya »

Друзья, нужна помощь.
есть задача найти в файле искомое значение(в виде даты - 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 одну минуту и проверяет наличие получившегося значения в файле,
если таковое значение есть, выдает переменную с таким значением и печатает содержимое этой переменной.
# если такого значения снова не оказалось, то вычитает еще одну минуту и снова проверяет и так до тех пор пока не найдет совпадение.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 18483
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: циклы в bash

Сообщение Bizdelnick »

Как-то Вы не с той стороны к задаче подошли. Не надо тыщу раз проходить по файлу, инкрементируя искомое время. Я ведь правильно понимаю, что это лог, в котором записи заведомо упорядочены по времени? Перебирайте в цикле строки по одной (while read …), пока не дойдёте до той, в которой время не меньше искомого. Для сравнения преобразуйте время в формат %s.
Если это не лог, и порядок следования строк произвольный, решение будет таким же, просто сперва надо будет отсортировать строки по возрастанию времени.
Добавлено (18:30):
kosstya писал:
06.05.2021 18:06
если такой строки нет, то искать ближайшее занчение.
Если имеется в виду ближайшее значение как до, так и после искомого времени, то надо сохранять одну предыдущую прочитанную строку и при нахождении той, которая содержит время после искомого, проверять, какая из двух ближе.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

kosstya
Сообщения: 4
ОС: ubuntu

Re: циклы в bash

Сообщение kosstya »

да это лог.
Идея ваша звучит разумнее, но мне все равно не хватает опыта, чтобы это реализовать.
В любом случае, спасибо большое. Буду думать в этом направлении.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 18483
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: циклы в bash

Сообщение Bizdelnick »

kosstya писал:
06.05.2021 20:18
Идея ваша звучит разумнее, но мне все равно не хватает опыта, чтобы это реализовать.
А в чём проблема, собственно? Задаёте референсное время

Код: Выделить всё

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 вернёт текущее время.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

kosstya
Сообщения: 4
ОС: ubuntu

Re: циклы в bash

Сообщение kosstya »

попробую разобраться, СПАСИБО!!
Спасибо сказали:

kosstya
Сообщения: 4
ОС: ubuntu

Re: циклы в bash

Сообщение kosstya »

пошел немного другим путем. Коряво конечно и долго, но работает. Так что оставлю здесь, вдруг кому пригодится))
Добавлено (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'
Спасибо сказали: