Как можно сравнить две даты в оболочке?
Вот пример того, как я хотел бы использовать это, хотя это не работает как есть:
todate=2013-07-18
cond=2013-07-15
if [ $todate -ge $cond ];
then
break
fi
Как мне достичь желаемого результата?
shell-script
shell
date
Абдул
источник
источник
Ответы:
Правильный ответ все еще отсутствует:
Обратите внимание, что для этого требуется дата GNU. Эквивалентный
date
синтаксис для BSDdate
(подобный найденному в OSX по умолчанию)date -j -f "%F" 2014-08-19 +"%s"
источник
timeout=$(`date +%Y%m%d%H%M%S` + 500)
) явно неверна.date -d 2013-07-18 +%s%N
Вам не хватает формата даты для сравнения:
Вам тоже не хватает циклических структур, как вы планируете получать больше дат?
источник
date
с MacOS.date -d
не является стандартным и не работает на типичной UNIX. На BSD он даже пытается установить значение кенеляDST
.Можно использовать стандартное сравнение строк для сравнения хронологического порядка [строк в формате год, месяц, день].
К счастью, когда [строки, которые используют формат YYYY-MM-DD] сортируются * в алфавитном порядке, они также сортируются * в хронологическом порядке.
(* - отсортировано или сравнено)
Ничего особенного в этом деле не нужно. ура!
источник
if [ $(sed -e s/-//g <<< $todate) -ge $(sed -e s/-//g <<< $cond) ];
... Этот формат даты был разработан для сортировки с использованием стандартной буквенно-цифровой сортировки или для-
сортировки и численной сортировки.Это проблема не циклических структур, а типов данных.
Эти даты (
todate
иcond
) являются строками, а не числами, поэтому вы не можете использовать оператор "-ge" дляtest
. (Помните, что обозначение в квадратных скобках эквивалентно командеtest
.)Что вы можете сделать, это использовать другую запись для ваших дат, чтобы они были целыми числами. Например:
выдаст целое число, например 20130715, 15 июля 2013 г. Затем вы сможете сравнить свои даты с "-ge" и эквивалентными операторами.
Обновление: если указаны ваши даты (например, вы читаете их из файла в формате 2013-07-13), то вы можете легко предварительно обработать их с помощью tr.
источник
Оператор
-ge
работает только с целыми числами, которых нет у ваших дат.Если ваш скрипт представляет собой скрипт bash или ksh или zsh, вы можете использовать
<
вместо этого оператор. Этот оператор недоступен в тире или других оболочках, которые не выходят за рамки стандарта POSIX.В любой оболочке вы можете преобразовать строки в числа, соблюдая порядок дат, просто удалив тире.
Кроме того, вы можете перейти на традиционные и использовать
expr
утилиту.Поскольку запуск подпроцессов в цикле может быть медленным, вы можете предпочесть выполнить преобразование, используя конструкции обработки строки оболочки.
Конечно, если вы можете получить даты без дефисов, вы сможете их сравнить
-ge
.источник
Я конвертирую строки в метки времени Unix (секунды с 1.1.1970 0: 0: 0). Это можно легко сравнить
источник
date
что поставляется с MacOS.Существует также этот метод из статьи под названием: Простой расчет даты и времени в BASH с unix.com.
Эти функции являются выдержкой из скрипта в этой теме!
использование
источник
date
что поставляется с MacOS.date
вgdate
.Bash конкретный ответ
Так как я люблю уменьшать количество вилок и bash, я допускаю много хитростей, поэтому у меня есть цель:
Ну теперь:
Это позволит заново заполнить обе переменные
$todate
и$cond
, используя только одну разветвленную ветвь, с выходом, которыйdate -f -
берет stdio для чтения одной даты построчно.Наконец, вы можете разорвать ваш цикл с
Или как функция :
Использование встроенной функции bash ,
printf
которая может отображать дату и время с секундами от эпохи (см .man bash
;-)Этот скрипт использует только один форк.
Альтернатива с ограниченными вилками и функцией чтения даты
Это создаст выделенный подпроцесс (только один форк):
Поскольку вход и выход открыты, запись fifo может быть удалена.
Функция:
Замечание Для предотвращения таких бесполезных форков, как
todate=$(myDate 2013-07-18)
переменная, должна быть установлена самой функцией. И чтобы разрешить свободный синтаксис (с или без кавычек для строки даты), имя переменной должно быть последним аргументом.Тогда сравнение даты:
может сделать:
если вне петли.
Или используйте функцию оболочки bash:
или же
(Которые не совсем такие же:
.sh
содержат полный сценарий тестирования, если не получены)источник
date -f -
может уменьшить потребность в ресурсах.даты - это строки, а не целые числа; Вы не можете сравнить их со стандартными арифметическими операторами.
один подход, который вы можете использовать, если гарантированно будет разделитель
-
:Это работает еще как
bash 2.05b.0(1)-release
.источник
Вы также можете использовать встроенную функцию mysql для сравнения дат. Это дает результат в «днях».
Просто вставьте значения
$DBUSER
и$DBPASSWORD
переменные в соответствии с вашими.источник
FWIW: на Mac, кажется, что в дату будет введена только дата типа «2017-05-05», к которой будет добавлено текущее время, и вы будете получать разное значение каждый раз, когда будете конвертировать его во время эпохи. чтобы получить более согласованное время эпохи для фиксированных дат, включите фиктивные значения для часов, минут и секунд:
Это может быть странностью, ограниченной версией даты, поставляемой с macOS .... протестированной на macOS 10.12.6.
источник
Повторяя ответ @Gilles («Оператор -ge работает только с целыми числами»), вот пример.
datetime
целочисленные преобразования вepoch
ответ @ mike-q на https://stackoverflow.com/questions/10990949/convert-date-time-string-to-epoch-in-bash :"$curr_date"
больше чем (более поздний чем)"$old_date"
, но это выражение неправильно оценивается какFalse
:... показано явно, здесь:
Целочисленные сравнения:
источник
Причина, по которой это сравнение не работает с дефисной строкой даты, заключается в том, что оболочка предполагает, что число с начальным 0 является восьмеричным, в данном случае это месяц "07". Были предложены различные решения, но самым быстрым и простым является удаление дефисов. Bash имеет функцию подстановки строк, которая делает это быстрым и легким, тогда сравнение может быть выполнено как арифметическое выражение:
источник