Quero criar um script Bash que produza o seguinte:
Chile: 03:46am, Friday, 27 September, 2024
Tierra Del Fuego: 03:46am, Friday, 27 September, 2024
Falkland Islands: 03:46am, Friday, 27 September, 2024
South Georgia and the South Sandwich Islands: 04:46am, Friday, 27 September, 2024
UTC: 06:46am, Friday, 27 September, 2024
South Africa: 08:46am, Friday, 27 September, 2024
Port Alfred, Iles Crozet: 10:46am, Friday, 27 September, 2024
Western Australia: 14:46pm, Friday, 27 September, 2024
South Australia: 16:16pm, Friday, 27 September, 2024
VIC, NSW, ACT, and QLD, Australia: 16:46pm, Friday, 27 September, 2024
New Zealand: 18:46pm, Friday, 27 September, 2024
Consegui fazer isso até agora usando o seguinte código:
#Chile
location="America/Santiago"
label="Chile"
time=$(TZ=$location date "+%H:%M%p")
date=$(TZ=$location date "+%A, %d %B, %Y")
echo "$label: $time, $date"
...e então ter vários blocos do mesmo código, com localização e rótulo alterados conforme necessário.
Isso é ok, mas é um arquivo de 103 linhas. Quero aprender como usar matrizes associativas para realizar a mesma tarefa sem nenhuma outra razão além de simplesmente aprender.
Eu criei o array em si da seguinte maneira:
# Declare an associative array
declare -A locationsArray
# Add elements to the associative array
locationsArray[America/Santiago]="Chile"
locationsArray[America/Argentina/Ushuaia]="Tierra Del Fuego"
locationsArray[Atlantic/Stanley]="Falkland Islands"
locationsArray[Atlantic/South_Georgia]="South Georgia and the South Sandwich Islands"
locationsArray[Etc/UTC]="UTC"
locationsArray[Africa/Johannesburg]="South Africa"
locationsArray[Asia/Dubai]="Port Alfred, Iles Crozet"
locationsArray[Australia/Perth]="Western Australia, Australia"
locationsArray[Australia/Adelaide]="South Australia, Australia"
locationsArray[Australia/Melbourne]="VIC, NSW, ACT, and QLD, Australia"
locationsArray[Pacific/Auckland]="New Zealand"
Agora só preciso pegar uma chave do array e seu valor associado (por exemplo, "América/Santiago" e "Chile") e iterar por todo o array usando o código acima como modelo.
Como posso fazer isso?
Obrigado.
Talvez uma matriz associativa não seja a melhor ferramenta aqui, você pode fazer:
Note que a diretiva format do
-2
bash se refere ao horário em que a instância do bash foi iniciada. Isso garante que você obtenha uma saída para o mesmo horário em todas as regiões, mesmo se você tiver iniciado o script em e ele levar mais de 0,1 segundos¹ para ser executado.printf
%T
10:46:59.9
Você pode iterar sobre as chaves de matrizes associativas no bash com:
Mas cuidado, a ordem não é determinística.
Em
zsh
², você pode obter chaves e valores ao mesmo tempo com:Mas aí também a ordem não é determinística.
Matrizes associativas são úteis para procurar valores individuais de forma eficiente. Há um custo maior na atribuição, pois uma tabela hash precisa ser construída, mas a pesquisa é eficiente. Aqui, como você quer fazer um loop uma vez em todas as entradas, isso anula completamente o propósito e se torna significativamente pior tanto funcionalmente quanto em termos de desempenho. Uma matriz normal faria mais sentido.
Em zsh:
O Bash não suporta loop com mais de uma variável, mas você pode fazer:
Em vez disso, lá. Ou:
Mas isso é mais trabalhoso de escrever do que a abordagem heredoc CSV mencionada acima. Em vez de um here doc, você também pode ter o CSV com o mapeamento em um arquivo separado que pode ser mantido separadamente do script e usar
< /path/to/that/file
em vez de<< 'EOF'...EOF
.¹ Ou horas , por exemplo, porque é canalizado para um comando que não lê sua entrada por um tempo.
² Onde o equivalente ao bash
printf
seria%T
por meio de sua expansãostrftime
interna (e da$EPOCHSECONDS
variável) ou prompt como comprint -rP -- "$region %D{...}"
(embora apenas para o tempo atual com o último).Modificando o código atual do OP para usar a matriz associativa do OP:
Isso gera:
NOTAS:
South Australia, Australia
a saída esperada nº 2South Australia
retira o país, enquanto para a entrada nº 2VIC, NSW, ACT, and QLD, Australia
a saída esperada nº 2VIC, NSW, ACT, and QLD, Australia
não retira o país; o OP precisará fornecer as regras para se/quando retirar as strings da entrada ou atualizar a pergunta para garantir que as entradas e saídas correspondamModificando o código acima para usar uma variação da
bash / printf
chamada de Stéphane:Isso gera:
Para imprimir os resultados em uma ordem específica, o OP pode alternar para uma matriz normal, certificando-se de preencher a matriz na mesma ordem da saída desejada, por exemplo:
Isso gera: