Como duas datas podem ser comparadas em um shell?
Aqui está um exemplo de como eu gostaria de usar isso, embora não funcione como está:
todate=2013-07-18
cond=2013-07-15
if [ $todate -ge $cond ];
then
break
fi
Como posso alcançar o resultado desejado?
shell-script
shell
date
Abdul
fonte
fonte
Respostas:
A resposta correta ainda está faltando:
Observe que isso requer data GNU. A
date
sintaxe equivalente para BSDdate
(como encontrada no OSX por padrão) édate -j -f "%F" 2014-08-19 +"%s"
fonte
timeout=$(`date +%Y%m%d%H%M%S` + 500)
) está obviamente errada.date -d 2013-07-18 +%s%N
Está faltando o formato da data para a comparação:
Você também está perdendo estruturas em loop, como planeja obter mais datas?
fonte
date
fornecido com o macOS.date -d
não é padrão e não funciona em um UNIX típico. No BSD, ele ainda tenta definir o valor do kenelDST
.Pode usar uma comparação de cadeias padrão para comparar a ordem cronológica [de cadeias em um formato de ano, mês, dia].
Felizmente, quando [cadeias que usam o formato AAAA-MM-DD] são classificadas * em ordem alfabética, elas também são classificadas * em ordem cronológica.
(* - classificado ou comparado)
Nada extravagante necessário neste caso. yay!
fonte
if [ $(sed -e s/-//g <<< $todate) -ge $(sed -e s/-//g <<< $cond) ];
… Esse formato de data foi projetado para ser classificado usando a classificação numérica alfa padrão ou para-
ser separado e classificado numericamente.Este não é um problema de estruturas em loop, mas de tipos de dados.
Essas datas (
todate
econd
) são cadeias de caracteres, não números, portanto você não pode usar o operador "-ge" detest
. (Lembre-se de que a notação entre colchetes é equivalente ao comandotest
.)O que você pode fazer é usar uma notação diferente para suas datas, para que sejam números inteiros. Por exemplo:
produzirá um número inteiro como 20130715 para 15 de julho de 2013. Em seguida, você pode comparar suas datas com "-ge" e operadores equivalentes.
Atualização: se suas datas são fornecidas (por exemplo, você as lê de um arquivo no formato 13/07/2013), você pode pré-processá-las facilmente com tr.
fonte
O operador
-ge
trabalha apenas com números inteiros, que não são suas datas.Se o seu script for um script bash ou ksh ou zsh, você poderá usar o
<
operador. Este operador não está disponível no painel ou em outros shells que não vão muito além do padrão POSIX.Em qualquer shell, você pode converter as seqüências de caracteres em números, respeitando a ordem das datas, simplesmente removendo os traços.
Como alternativa, você pode ir tradicional e usar o
expr
utilitário.Como a invocação de subprocessos em um loop pode ser lenta, você pode preferir fazer a transformação usando construções de processamento de cadeia de shell.
Obviamente, se você puder recuperar as datas sem os hífens, poderá compará-las
-ge
.fonte
Eu converto as Strings em unix-timestamps (segundos desde 1.1.1970 0: 0: 0). Estes podem ser comparados facilmente
fonte
date
que acompanha o macOS.Também existe este método no artigo intitulado: Calibração simples de data e hora no BASH do unix.com.
Essas funções são um trecho de um script nesse segmento!
Uso
fonte
date
que acompanha o macOS.date
paragdate
.resposta específica do bash
Como gosto de reduzir os garfos e o bash permitem muitos truques, existe o meu objetivo:
Bem agora:
Isso irá preencher novamente as duas variáveis
$todate
e$cond
, usando apenas um fork, com exceção dodate -f -
que leva o stdio para ler uma data por linha.Finalmente, você pode quebrar seu ciclo com
Ou como uma função :
Usando o built-in do bash ,
printf
que pode renderizar data e hora com segundos a partir da época (consulteman bash
;-)Este script usa apenas um garfo.
Alternativa com garfos limitados e função de leitor de data
Isso criará um subprocesso dedicado (apenas um fork):
Como entrada e saída estão abertas, a entrada quino pode ser excluída.
A função:
Nota Para evitar garfos inúteis como
todate=$(myDate 2013-07-18)
, a variável deve ser definida pela própria função. E para permitir sintaxe livre (com ou sem aspas para a cadeia de dados), o nome da variável deve ser o último argumento.Data da comparação:
pode render:
se estiver fora de um loop.
Ou use a função bash do conector do shell:
ou
(Que não são exatamente iguais:
.sh
contém script de teste completo, se não for fornecido)fonte
date -f -
pode reduzir os requisitos de recursos.datas são strings, não inteiros; você não pode compará-los com operadores aritméticos padrão.
uma abordagem que você pode usar, se for garantido que o separador é
-
:Isso funciona já em
bash 2.05b.0(1)-release
.fonte
Você também pode usar a função embutida do mysql para comparar as datas. Dá o resultado em 'dias'.
Basta inserir os valores
$DBUSER
e$DBPASSWORD
variáveis de acordo com o seu.fonte
FWIW: no Mac, parece que alimentar apenas uma data como "2017-05-05" adicionará a hora atual à data e você terá um valor diferente cada vez que a converter para a época. para obter um tempo de época mais consistente para datas fixas, inclua valores fictícios por horas, minutos e segundos:
Isso pode ser uma raridade limitada à versão da data fornecida com o macOS .... testada no macOS 10.12.6.
fonte
Fazendo eco da resposta do @Gilles ("O operador -ge funciona apenas com números inteiros"), aqui está um exemplo.
datetime
conversões de número inteiro paraepoch
, de acordo com a resposta de @ mike-q em https://stackoverflow.com/questions/10990949/convert-date-time-string-to-epoch-in-bash :"$curr_date"
é maior que (mais recente que)"$old_date"
, mas essa expressão é avaliada incorretamente comoFalse
:... mostrado explicitamente, aqui:
Comparações de números inteiros:
fonte
A razão pela qual essa comparação não funciona bem com uma string de data hifenizada é que o shell assume que um número com 0 inicial é um octal, nesse caso, o mês "07". Foram propostas várias soluções, mas a mais rápida e fácil é retirar os hífens. O Bash possui um recurso de substituição de string que torna isso rápido e fácil, então a comparação pode ser realizada como uma expressão aritmética:
fonte