bash
na verdade suporta algo muito próximo do que você primeiro tentou .
INPUT1=/tmp/dir1
INPUT2=/tmp/dir2
INPUT3=/tmp/dir3
for s in INPUT{1..3}; do
echo ${!s}
done
Isso funciona porque:
-
INPUT{1..3}
expande para INPUT1 INPUT2 INPUT3
. (É equivalente a INPUT{1,2,3}
.)
-
Em que $s
é a expansão de s
, ${!s}
é a expansão da expansão de s
.
Por exemplo, na primeira iteração do loop, se $s
aparecer, ele será expandido para INPUT1
. Se $INPUT1
aparecer, seria expandido para /tmp/dir1
. Assim, ${!s}
é expandido para /tmp/dir1
.
Esse tipo de expansão de parâmetros é chamado expansão indireta . Nesta situação e em muitos outros, a sintaxe !
integrada obtém isso de maneira mais compacta e elegante do que eval
.
Para obter mais informações, consulte É possível criar nomes de variáveis de outras variáveis no bash? em estouro de pilha .
Algumas ressalvas (que também se aplicam a algumas das outras respostas que foram postadas):
-
Se algum valor de INPUTn
puder conter espaço em branco 1 (como espaços 2 , guias ou newlines ) ou (como $varname
), citando deve ser usado.
Aspas simples para a tarefa são melhores se você quiser evitar toda a expansão lá: INPUT1=/tmp/dir1
→ INPUT1='/tmp/dir with spaces'
(Apenas um caractere de aspas '
é tratado especialmente, pois ele funcionará como a marca de fechamento de citações.)
Mas use aspas duplas para permitir que a variável seja expandida:
echo ${!s}
→ echo "${!s}"
(Isso funciona mesmo se o valor após a expansão contiver um $
. O conteúdo expandido não será expandido novamente.
Por exemplo, BAZ=QUUX FOO='BAR $BAZ'; echo "$FOO"
imprime BAR $BAZ
, não BAR QUUX
.)
-
Se algum dos INPUTn
assumir um valor que echo
interpretaria como uma opção em vez de texto para imprimir, substitua echo
por printf '%s\n'
. 3
Atualmente, isso é -
seguido por mais um e
, E
ou n
. Mas você provavelmente deve considerar qualquer coisa que comece com -
como perigosa no caso de futuras versões bash adicionarem novas opções.
Embora, em termos de sintaxe, a expansão indireta apresentada acima seja quase tão simples quanto fazê-lo com uma matriz, você ainda pode querer usar uma matriz porque:
- Pode refletir melhor o significado subjacente do problema que você está tentando resolver.
- Você pode usar outros recursos de matrizes para resolver esse problema.
Talvez você pretendesse /tmp/dir1
, /tmp/dir2
e /tmp/dir3
como exemplos opacos que podem ser substituídos por qualquer coisa.
Mas se você realmente quiser criar uma matriz desses valores específicos, recomendo:
input=(/tmp/dir{1..3})
Da mesma forma, se o seu objetivo for percorrer /tmp/dir1
, /tmp/dir2
e /tmp/dir3
e executar alguma ação com cada um, você não precisará armazená-los em nenhum tipo de variável :
for s in /tmp/dir{1..3}; do
echo $s
done
Se os valores de s
contiverem espaços em branco ou caracteres especiais (veja acima), cite-os, mas deixe o intervalo de {...}
sem aspas separadamente, citando o texto à esquerda e à direita dele - não ser expandido se for cotado, mesmo entre aspas duplas.
for s in '/tmp/dir '{1..3}' with spaces'; do
echo "$s"
done
Isso imprime:
/tmp/dir 1 with spaces
/tmp/dir 2 with spaces
/tmp/dir 3 with spaces
E se seu objetivo for realmente apenas imprimir /tmp/dir1
, /tmp/dir2
e /tmp/dir3
, cada um em sua própria linha, então esse único comando 3 é suficiente:
printf '%s\n' /tmp/dir{1..3}
1 : o shell divide o texto em palavras no espaço em branco ou, se a variável IFS
estiver definida, nos separadores de campos especificados. Mas normalmente você não precisa se preocupar com IFS
, a menos que você tenha definido você mesmo.
2 : echo hello world
realmente funciona: ela imprime hello world
, como echo 'hello world'
. Isso ocorre porque echo
imprime um único espaço entre cada argumento ecoado . No entanto, echo hello world
não é equivalente a echo 'hello world'
: a primeira ainda imprime hello world
enquanto a segunda imprime hello world
.
3 : Para mais informações sobre bash
' printf
builtin, consulte o saída de help printf
ou esta seção do manual de Bash . printf
também é um executável que pode ser chamado de outros shells (e nessa capacidade é padronizado ).