Veja o final para o resultado final.
for i in {1..1000000..1}
do
echo "$i,$(date -d "2017-08-01 + $(shuf -i 1-31 -n 1) days" +'%Y-%m-%d')" >> $F
done;
Os loops da shell são lentos e há duas coisas principais que tornam esse loop extra muito lento:
- Abrindo e anexando a um arquivo em cada iteração.
- Duas execuções de utilitários externos (
shuf
edate
) em cada iteração. Oecho
provavelmente está embutido no shell, de modo que incorre em menos sobrecarga.
O redirecionamento de saída é mais facilmente corrigido:
for i in {1..1000000..1}
do
echo "$i,$(date -d "2017-08-01 + $(shuf -i 1-31 -n 1) days" +'%Y-%m-%d')"
done >"$F"
Isso só abre o arquivo de saída uma vez e o mantém aberto pela duração do loop.
O resto do código pode ser feito de forma mais eficiente com awk
e GNU date
(desde que você esteja usando shuf
, suponho que você esteja em um sistema Linux, o que significa que é muito provável que date
é na verdade GNU date
).
awk 'END { for (i=0;i<100;++i) { printf("2017-08-01 + %d days\n", 1+int(31*rand())) }}' /dev/null
Essa coisa gera 100 linhas como
2017-08-01 + 22 days
2017-08-01 + 31 days
2017-08-01 + 11 days
2017-08-01 + 27 days
2017-08-01 + 27 days
2017-08-01 + 20 days
(etc.)
Vamos colocar isso no GNU date
. O GNU date
tem este sinalizador, -f
, que nos permite alimentá-lo em lote com várias especificações de data, por exemplo, aquelas produzidas pelo nosso programa awk
:
awk 'END { for (i=0;i<100;++i) { printf("2017-08-01 + %d days\n", 1+int(31*rand())) }}' /dev/null |
date -f - +'%Y-%m-%d'
Agora chegamos
2017-08-23
2017-08-27
2017-08-21
2017-08-29
2017-08-25
2017-08-17
2017-08-07
(etc.)
Então é só adicionar o ID único (um inteiro sequencial) a cada linha:
awk 'END { for (i=0;i<100;++i) { printf("2017-08-01 + %d days\n", 1+int(31*rand())) }}' /dev/null |
date -f - +'%Y-%m-%d' |
awk -vOFS=',' '{ print NR, $0 }'
Isso te dá
1,2017-08-06
2,2017-08-17
3,2017-08-25
4,2017-08-28
5,2017-08-14
6,2017-08-15
7,2017-08-17
8,2017-08-10
9,2017-08-16
10,2017-08-08
(etc.)
E agora terminamos. E no processo, eu esqueci completamente que tínhamos um loop de shell. Acontece que não é necessário.
Apenas aumente o 100
para qualquer valor desejado e ajuste o gerador de números aleatórios para atender às suas necessidades. rand()
retorna um valor de ponto flutuante tal que 0 < = number < 1.
Obviamente, se você quer apenas datas aleatórias em agosto (um mês com 31 dias), você pode ignorar date
ao todo:
awk 'END { for (i=1;i<=100;++i) { printf("%d,2017-08-%02d\n", i, 1+int(31*rand())) }}' /dev/null
Com o GNU awk
e o awk
do Mike ( mawk
), mas não com o BSD awk
, você pode até mesmo manipular a data corretamente diretamente em awk
:
awk 'END { for (i=1;i<=100;++i) { printf("%d,%s\n", i, strftime("%Y-%m-%d", 1501545600 + int(2678400*rand()),1 )) }}' /dev/null
Agora, estamos lidando com timestamps do Unix, e não com dias. 1501545600 corresponde a "terça-feira 1 de agosto às 00:00:00 UTC 2017" e há 2678400 segundos em 31 dias.