Bash for loops me confundiu até que aprendi essas 4 regras de expansão

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.

1
Por Zunaid Ali

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

4
Por Will Verduzco

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.

5
Por Graeme Pavão

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

"${my_arr[@]}"

Múltiplas palavras (Bash)

Não

"${my_arr[*]}"

Uma palavra (Bash)

Não

${my_arr[@]}

Múltiplas palavras (Bash)

Sim

${my_arr[*]}

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.

2
Por Bobby Jack
Este artigo foi útil?
Gostei0Não Gostei0

Related posts

5 exercícios de codificação que melhoraram minhas habilidades de resolução de problemas

O tempo frio pode arruinar lentamente o seu telefone – veja como protegê-lo neste inverno

8 configurações úteis do Raspberry Pi que você pode alterar (e como)