Seu script lê o arquivo inteiro em uma variável e depois repete o valor dessa variável. Isso tem três problemas:
- No caso mais geral, pode-se desconhecer o tamanho do arquivo de entrada, o que significa que, em algumas circunstâncias, a variável pode se tornar muito grande.
- Repetir o valor sem aspas da variável dependerá do shell dividir os dados em espaços em branco (espaços, tabulações e novas linhas). Se os dados contiverem espaços em branco separados das novas linhas, o loop provavelmente fará a coisa errada.
- O shell executará a globalização do nome de arquivo nos valores da variável sem aspas antes de fazer o loop sobre ela. Isso significa que, se os dados contiverem padrões de globbing, como
*
ou[...]
, eles serão correspondidos aos nomes de arquivos existentes.
Esta resposta usa o fato de que os timestamps usados são são no sentido de que, mais tarde, eles datilografam depois dos anteriores (pelo menos no local POSIX).
#!/bin/bash
while IFS= read -r line; do
timestamp=${line%:*} # Remove ":ERR" at the end
timestamp=${timestamp#*:*:} # Remove numbers from start ("0001:3002:")
if [[ "$timestamp" > "$1" ]]; then
# According to the current locale, the timestamp in "$timestamp"
# sorts after the timestamp in "$1".
printf "Greater: %s\n" "$line"
fi
done <file
Este script receberá um timestamp no mesmo formato que está no arquivo como seu único argumento. Ele itera sobre o conteúdo do arquivo file
e, para cada linha, analisa o registro de data e hora e o compara com o registro de data e hora na linha de comando. A comparação é feita usando o operador >
em bash
e será true se o registro de data e hora no arquivo for classificado (lexicograficamente) após o registro de data e hora determinado na localidade atual. Se a comparação for verdadeira, a linha do arquivo é impressa.
As duas substituições separadas para analisar o timestamp da linha, excluindo partes do final e início da linha, podem ser substituídas por
timestamp=$( cut -d ':' -f 3,4 <<<"$line" )
mas isso seria mais lento quando estiver chamando um utilitário externo.
Teste:
$ bash script.sh '2018/07/16:12.36.00'
Greater: 0008:3002:2018/07/16:12.36.02:ERR
Greater: 0009:3002:2018/07/16:12.36.15:ERR
Se você deseja produzir apenas o registro de data e hora do arquivo em vez da linha original, altere "$line"
para "$timestamp"
no comando printf
.
Nesse caso, você também pode acelerar as coisas fazendo o loop assim:
#!/bin/bash
cut -d ':' -f 3,4 file |
while IFS= read -r timestamp; do
if [[ "$timestamp" > "$1" ]]; then
# According to the current locale, the timestamp in "$timestamp"
# sorts after the timestamp in "$1".
printf "Greater: %s\n" "$timestamp"
fi
done
Aqui, usamos cut
para obter as colunas 3rd e 4th :
-delimited do arquivo (o timestamp), o que significa que não precisamos fazer nenhuma análise das linhas originais.
Relacionados: