Seu problema está nos espaços nos dados. O shell dividirá a string em palavras em todos os espaços e o loop for
irá iterar essas palavras.
(Para uma solução que não substitua variable_list
por um array, veja o final desta resposta.)
Em vez disso, use uma matriz adequada:
variable_list=(
"any:any:-a -b -c any"
"one:one:-c -b -f -m mul"
"mul:one:-c -b -f -m mul"
)
for var in "${variable_list[@]}"; do
c1=$( cut -d':' -f1 <<<"$var" )
c2=$( cut -d':' -f2 <<<"$var" )
c3=$( cut -d':' -f3- <<<"$var" )
printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done
O uso de uma matriz garante que você possa acessar cada conjunto individual de variáveis como sua própria entrada de matriz, sem depender que elas sejam delimitadas por novas linhas ou por algum outro caractere.
O código também está usando "here-strings" em bash
para enviar a string para cut
(em vez de echo
e um pipe).
Ou com muito mais eficiência,
variable_list=(
"any:any:-a -b -c any"
"one:one:-c -b -f -m mul"
"mul:one:-c -b -f -m mul"
)
for var in "${variable_list[@]}"; do
IFS=':' read -r c1 c2 c3 <<<"$var"
printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done
A definição de IFS
para dois-pontos por read
fará com que read
divida a entrada em dois pontos (e não em espaços, tabulações e novas linhas).
Observe que toda a cotação acima é significativa. Sem as aspas duplas, o shell executaria a divisão de palavras e a globalização de nomes de arquivos nos valores das variáveis variable_list
, var
e três c
.
Relacionados:
- Quando é necessário fazer uma cotação dupla?
- Por que o printf é melhor que o eco?
- Os backticks (ou seja, 'cmd') em shells * sh foram preteridos?
Se tudo que você procura é uma saída específica, então você pode trapacear um pouco:
variable_list=(
"any:any:-a -b -c any"
"one:one:-c -b -f -m mul"
"mul:one:-c -b -f -m mul"
)
( IFS=':'; set -f; printf 'c1==>%s and c2==>%s and c3==>%s\n' ${variable_list[@]} )
Isso executa o printf
em uma subshell para que a opção de configuração IFS
e -f
( noglob
) não afete o restante do script. Configurar IFS
para dois-pontos aqui fará com que o shell expanda a matriz sem aspas variable_list
em três conjuntos de três argumentos para printf
. printf
imprimirá os três primeiros de acordo com sua string de formato e, em seguida, reutilizará esse formato para o próximo conjunto de três argumentos, até que todos os argumentos tenham sido processados.
O set -f
impede que a expansão sem aspas de variable_list
acione a globalização de nomes de arquivos, caso haja algum caractere de globalização de nomes de arquivos.
Usando uma string delimitada por nova linha:
variable_list="
any:any:-a -b -c any
one:one:-c -b -f -m mul
mul:one:-c -b -f -m mul"
while IFS= read -r var; do
IFS=':' read -r c1 c2 c3 <<<"$var"
printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done <<<"$variable_list"
Isto lê os dados da string como se viesse de um arquivo.
Relacionados: