puxando linhas relacionadas com a data

2

Eu tenho um arquivo de texto que é sort ed pelo primeiro campo, que é mês / dia (por exemplo: 02-20)

Estou usando grep no arquivo de texto, mas é mais fácil fazer isso com a data de hoje, usando o comando date em um script.

Gostaria de destacar os três dias anteriores, a data de hoje e os próximos cinco dias ... mas não conheço uma maneira fácil de lidar com o final do mês / no mês seguinte. Eu poderia, digo, codificar isso? Mas eu estava procurando uma solução elegante para o problema, então estou buscando sugestões.

Eu prefiro usar comandos regulares para que o script seja o mais portátil possível.

ie: por portáteis, quero dizer não apenas limitado a máquinas Linux / GNU (e / ou ter que instalar utilitários específicos para fazer tudo rodar). Atualmente eu acho que estou em uma máquina BSD, e eu estive na maioria dos sabores do UNIX (Solaris, blah, blah, blah) - e provavelmente será no futuro.

Eu pegaria algo mais complicado para programar / script, que usa ferramentas muito básicas, por ter que lembrar de instalar pacotes toda vez que eu estivesse com um sabor diferente do UNIX (quando eu poderia simplesmente scp no meu diretório de scripts e tem que trabalhar).

FYI: o sinalizador date -d atual define o horário de verão:)

 -d dst  Set the system's value for Daylight Saving Time.

Ok, acabei de dar um exemplo (como solicitado) do tipo sobre dados no arquivo (é muito maior, obvs), mas não dei exemplos. Aqui está um caso extremo, ou seja: como lidar com o final do mês, sem programar em um teste para o final do mês, para cada mês (ou 4 tipos de mês: 30, 31, 28 e 29).

01-01   Something To Do Here    Notes that may run for a really long time
02-05   On the 5th of the Month         Do this other thing, because of X
02-06   The day after           Do this cleanup stuff
03-15   The Ides                Remember, remember the Brutus of December
03-29   Edge                    Does this show up on the 1st of April?
03-30   Edge2                   Does this show up on the 1st and 2nd?
03-31   Last day in the month   Shows?
04-01   Edge                    Does this show on 31st?  Or does it only show 03-35?
    
por user3082 18.06.2015 / 14:22

4 respostas

3

A data do GNU permite atribuir strings à opção -d , como -2 days e 5 days . A opção -f permite que essas cadeias sejam lidas de um arquivo ou pipe. Então, usando o GNU date e bash :

printf '%d days\n' {-2..5} | date -f - +%m-%d | grep -f - in_file

Atualizar

Se tcl for aceitável, aqui está um script para imprimir as datas:

#!/usr/bin/tclsh

set now [clock seconds]

for {set n -2} {$n<=5} {incr n} {
  set out_date [clock add $now $n days]
  puts [clock format $out_date -format %m-%d]
}

Apenas canalize a saída disso para grep -f - , conforme acima.

    
por 18.06.2015 / 14:40
1

Bem, aqui está um forro que parece fazer o trabalho ...

dt=$(date +%m-%d);for i in {-2..5}; do grep "$(echo "$dt"|awk -F"-" -v count=$i '{print $1"-0"$2+count}')" mtest; done

Você pode tornar isso uma função adicionando isso ao seu .bashrc ...

todolist(){  dt=$(date +%m-%d);for i in {-2..5}; do grep "$(echo "$dt"|awk -F"-" -v count=$i '{print $1"-0"$2+count}')" $1; done; }

e depois você só precisa ligar

todolist whateverthefilename.txt

Não é muito bonito, mas eu testei com seus dados.

$ echo -e "01-01   Something To Do Here    Notes that may run for a really long time\n02-05   On the 5th of the Month         Do this other thing,\nbecause of X\n02-06   The day after           Do this cleanup stuff\n03-15   The Ides                Remember, remember the Brutus of December">> mtest

$ dt=02-05; for i in {-2..5}; do grep "$(echo "$dt"|awk -F"-" -v count=$i '{print $1"-0"$2+count}')" mtest; done
02-05   On the 5th of the Month         Do this other thing,
02-06   The day after           Do this cleanup stuff
    
por 18.06.2015 / 21:17
1

Você pode usar touch para testar POSIXAMENTE a validade de uma string de data.

Vou usar algumas opções aqui.

  • %código%
    • Não crie um arquivo especificado se ele não existir. Não escreva mensagens de diagnóstico sobre essa condição.
  • -c

    • Use o horário especificado em vez do horário atual. O argumento da opção deve ser um número decimal da forma:

      [[CC]YY]MMDDhhmm[.SS]
      
    • Se a hora não puder ser representada como o registro de data e hora do arquivo, -t deve sair imediatamente com um status de erro.

    • Observe que os campos touch são opcionais.

E assim, por exemplo:

testtime()
        if      command -v touch >&2
        then    touch -c ''
                eval '  touch -ct"$1" ""
                        [ "$?" = '"$? ]"
        else    { touch; } 2>&3
        fi      3>&2 2>/dev/null

É muito cuidadoso lidar com assuntos portáveis, eu acho. Em testes com um GNU e uma herança (Solaris) [[CC]YY] , a ferramenta GNU retorna 1 para uma data ruim e 0 para uma boa, mas a versão da herança retorna 2 e 1 respectivamente. Tenho quase certeza de que o comportamento da antiga ferramenta Solaris é especificamente referenciado no raciocínio da especificação onde eu encontro:

  • Pelo menos uma implementação histórica de touch incrementou o código de saída se touch foi especificado e o arquivo não existia. Este volume de POSIX.1-2008 requer o status de saída zero se nenhum erro ocorrer.

Estou mais convencido quando comparo o comportamento de diferentes versões de minhas ferramentas de herança. O do conjunto de base - que é projetado para se comportar tanto quanto o conjunto original quanto possível e ainda ser útil em sistemas modernos - é o que retorna o 2 e o 1 como mencionado. No entanto, quando eu uso o executável -c - que é a versão que foi modificada para conformidade com os padrões conforme necessário - ela retorna exatamente como a ferramenta GNU.

Em qualquer caso, a função manipula o Solaris antigo, o Solaris modificado para conformidade e os comportamentos GNU, porque compara os resultados de uma chamada inicial para /usr/heirloom/bin/posix2001/touch em um operando de arquivo touch null < em> (que definitivamente não existe) contra uma segunda chamada no mesmo e retorna 0 para uma data boa ou 1 para uma data ruim. Ele retorna 127 e grava para stderr se '' não puder ser encontrado.

Veja como você pode usá-lo:

testtime MMDD0000 && echo good date || echo bad date

... onde MM e DD são sequências decimais de 2 dígitos representando a data que você deseja testar. Você também pode verificar tempos válidos dessa maneira - e até mesmo com um campo touch segundos.

    
por 18.06.2015 / 21:19
0

Eu postei minha primeira resposta ontem com muito pouco sono. Estou de volta e pronto para tentar novamente. Ao invés de tentar acordar as datas, eu decidi que estava sendo inteligente demais, então voltei e repensarei isso.

todolist(){ for i in {-2..5}; do grep "$(date -d "${date} +$i days" +%m-%d)" $1 ; done; };

Basta adicionar o one-liner ao seu .bashrc e depois alimentar o arquivo.

Desta vez, deixo a data fazer todo o trabalho. Recebi a dica aqui . Este pequeno número adicionará qualquer número de dias a partir da data de hoje e mostrará no formato que você precisa para o seu arquivo ...

date -d "${date} +$i days" +%m-%d)"

A função acima agora deve funcionar sem recorrer a valores codificados.

    
por 19.06.2015 / 14:54