Você já ficou confuso com as diferentes maneiras de usar arrays Bash? Ou talvez você esteja apenas aprendendo Bash e eles sejam os próximos da sua lista? Matrizes Bash podem agir de maneira estranha dependendo de como você as usa. Explicarei as circunstâncias confusas que você pode encontrar ao fazer isso.
Se você já escreveu scripts Bash no passado, provavelmente já encontrou o loop for. A sintaxe deles é um pouco estranha e as diferentes abordagens me confundiram até que eu entendesse as quatro regras fundamentais.
Gerenciar dados com seus scripts Bash é fácil quando você conhece arrays
Explorando dados, um índice por vez.
Vejamos um problema. O script a seguir processa um array de duas maneiras diferentes – entre aspas: "${my_arr[@]}" e sem aspas: ${my_arr[@]}:
my_arr=("one a" "two b") echo 'Using ${my_arr[@]}:' for item in ${my_arr[@]}; do echo " $item" done echo -e "n-----n" echo 'Using "${my_arr[@]}":' for item in "${my_arr[@]}"; do echo " $item" done
Existem dois itens na matriz, então por que ${my_arr[@]} (sem aspas) exibir quatro? O motivo é chamado de “divisão de palavras” e é o tópico que abordarei hoje.
HTG Wrapped 2025: 24 dias de tecnologia
24 dias de nossos hardwares, gadgets e tecnologia favoritos
Uma introdução rápida sobre como usar um loop for
Para aqueles que não estão familiarizados com arrays Bash e loops for, aqui está um rápido resumo. Se você for um criador de scripts Bash experiente, poderá pular esta seção.
Esta é uma string: “foo bar.” Está entre aspas (simples ou duplas) porque os espaços são ambíguos em programas de computador. O uso de aspas define explicitamente os limites para valores baseados em texto.
Bash pode tratar “foo bar” como uma única palavra, dependendo do contexto. Bash define uma palavra como “uma sequência de caracteres tratada como uma unidade pelo shell”. Se você ouvir o termo “palavra” no Bash, isso não significa palavras em inglês separadas por espaços. Usarei os termos “palavras Bash” e “palavras inglesas” para distingui-los.
Esta é uma matriz: my_arr=("foo" "bar"). É uma sequência de valores (dois neste caso) que são acessados um após o outro.
Um loop “for” geralmente é uma declaração de intenção de processar um array, alternando (iterando) sobre ele, permitindo que você execute ações em cada item individualmente.
for item in "${my_arr[@]}"; do echo "$item" done
“item” é chamado de iterador ou variável de loop. À medida que o loop for itera sobre cada valor da matriz, ele é colocado em “item”, que você pode usar para executar ações.
Existem várias maneiras de fazer loop em um array, mas esta é a mais comum.
Há também outra maneira de acessar itens em arrays usando um “*”—"${my_arr[*]}"– sobre o qual abordarei mais tarde.
A expansão de parâmetros divide a matriz
No Bash, um parâmetro é uma entidade que armazena um valor – por exemplo, uma variável é um parâmetro. Um parâmetro expansão é essencialmente o avaliação de um parâmetro – por exemplo, girando $foo em “valor” em tempo de execução.
Em termos de matrizes, dado my_arr=("one a" "two b"), "${my_arr[@]}" expande “my_arr” em “um a” e “dois b.” Quando usamos esse array em um loop for, cada palavra Bash (“um a” e “dois b”) é atribuída à variável do loop.
Vejamos um exemplo:
my_arr=("one a" "two b") echo 'Using "${my_arr[@]}":' for item in "${my_arr[@]}"; do echo " $item" done echo -e "n-----n" echo 'Using "${my_arr[*]}":' for item in "${my_arr[*]}"; do echo " $item" done
No primeiro loop, usar o “@” expande o array em valores separados, delineados pelos seus limites de string (por exemplo, “um a” e “dois b”).
No segundo loop, usar “*” expande a matriz em um valor – uma string.
O uso de aspas duplas em torno de cada array é crucial aqui, porque, como veremos a seguir, o Bash faz algo diferente se eles não estiverem entre aspas.
A divisão de palavras divide ainda mais cada palavra do Bash
Vimos o que acontece quando colocamos parâmetros de array entre aspas duplas, mas o que acontece quando os excluímos? Vamos dar uma olhada:
my_arr=("one a" "two b") echo 'Using ${my_arr[@]}:' for item in ${my_arr[@]}; do echo " $item" done echo -e "n-----n" echo 'Using ${my_arr[*]}:' for item in ${my_arr[*]}; do echo " $item" done
Ambas as matrizes geram quatro itens, mas por quê? Primeiro, lembre-se de que a expansão de parâmetros dividirá (expandirá) a matriz em torno dos limites das palavras (Bash) – por exemplo, “um a” e “dois b” produzem dois resultados. No entanto, quando esses parâmetros da matriz não possuem aspas duplas, o Bash os submete a um processamento adicional, chamado divisão de palavras.
A divisão de palavras significa simplesmente dividir cada palavra (Bash). Por exemplo, “um a” e “dois b” são divididos em “um”, “a”, “dois” e “b”. Por padrão, o Bash os divide em qualquer caractere de espaço em branco:
my_arr=($'onena' $'twotb' "three c") for item in ${my_arr[@]}; do echo "$item" done
$'...' é um tipo de cotação especial denominado cotação ANSI-C. Ao usá-los, o Bash substitui caracteres de sequência de escape (como “n”) por seus equivalentes literais (por exemplo, um caractere de nova linha). Além disso, “n” (nova linha) e “t” (tabulação) são considerados caracteres de espaço em branco.
No entanto, você pode especificar quais caracteres dividir as palavras usando a variável IFS (Internal Field Separator):
my_arr=('one+a' 'two+b') echo 'Default IFS:' for item in ${my_arr[@]}; do echo " $item" done echo -e "n-----n" echo 'IFS="+":' # Split words using "+". IFS="+" for item in ${my_arr[@]}; do echo " $item" done
A parte confusa é que a “divisão de palavras” é um processo distinto, e se você observar o comprimento do array (“#”), verá que ele é determinado pelo número de palavras Bash (elementos do array) e não por palavras divididas.
my_arr=('one a' 'two b') echo ${#my_arr[@]} echo "${#my_arr[@]}" echo ${#my_arr[*]} echo "${#my_arr[*]}"
3 técnicas de script Bash que todo usuário Linux deve conhecer
Desbloqueie o poder do Bash com estas técnicas simples.
Todos os formulários de parâmetros (array) que você viu hoje se expandem para algo. Somente os citados "${my_arr[*]}" expande os elementos em uma única string, mas o restante se expande em itens individuais da matriz. Todos os parâmetros não citados (por exemplo, ${my_arr[@]}) passam por processamento adicional – também conhecido como divisão de palavras (Bash).
|
Tipo |
Expande para… |
Divisão de palavras |
|
|
Múltiplas palavras (Bash) |
Não |
|
|
Uma palavra (Bash) |
Não |
|
|
Múltiplas palavras (Bash) |
Sim |
|
|
Múltiplas palavras (Bash) |
Sim |
Lembre-se de que uma “palavra” é uma sequência de caracteres contíguos, não necessariamente palavras em inglês separadas por espaços.
Você também deve ter notado que não citado ${my_arr[@]} e ${my_arr[*]} produzir o mesmo resultado.
Para encerrar, na maioria das vezes você usará "${my_arr[@]}" (com aspas), porque funciona como um array típico, mas é importante saber como as aspas afetam os parâmetros. Se você não citar seu array, poderá descobrir que os loops for não funcionam conforme o esperado.
Estas regras também se aplicam ao $@ e $* parâmetros especiais (também conhecidos como argumentos para funções).
8 truques do shell do Linux que mudam completamente a forma como os comandos funcionam
O shell faz muito mais do que executar comandos. Veja como o Bash expande sua entrada nos bastidores para que você possa escrever comandos mais limpos e confiáveis.