Por exemplo {a..c}{1..3}
, expande para a1 a2 a3 b1 b2 b3 c1 c2 c3
.
Se eu quisesse imprimir a1 b1 c1 a2 b2 c2 a3 b3 c3
, existe uma maneira análoga de fazer isso? Qual é a maneira mais simples?
Por exemplo {a..c}{1..3}
, expande para a1 a2 a3 b1 b2 b3 c1 c2 c3
.
Se eu quisesse imprimir a1 b1 c1 a2 b2 c2 a3 b3 c3
, existe uma maneira análoga de fazer isso? Qual é a maneira mais simples?
Você poderia fazer:
Que então diz ao shell para avaliar:
Para este caso em particular, acho que a opção dada por Stéphane Chazelas é a melhor.
Por outro lado, quando você expande coisas mais complexas, essa opção não escala bem. Então, você pode conseguir o mesmo com isso:
que retorna:
Parece um pouco confuso, mas agora, tenho um controle enorme na ordem, apenas alterando dois chars no comando acima; por exemplo:
isso se expandirá para:
Suponha que eu queira todos os
1
na segunda expansão, então o2
:Suponha que eu queira todos os
a
na terceira expansão, então ob
:Suponha que eu queira todos os
1
na quarta expansão, então o2
:Suponha que eu queira tudo
1a
no meio, então1b
, então2a
, então2b
:Você pode até mesmo, com a mesma facilidade, reverter qualquer ordem nas expansões acima, apenas adicionando um
r
ao comando anterior; por exemplo, o último:Nota_1 : normalmente, se esta expansão final for usada como uma lista de argumentos, o espaço à direita não é um problema; mas se você quiser se livrar dele, você pode adicionar, a qualquer um dos comandos acima, por exemplo
| sed 's/ $//'
; ou mesmo| sed 's/ $/\n/'
, para alterar esse espaço à direita por umnewline
Nota_2 : Nos exemplos acima, usei subconjuntos de dois elementos (ou seja: {a,b} e {1,2} ) apenas para simplificar na prova de conceito: você pode usar subconjuntos de qualquer comprimento finito e o comando correspondente, seria comparável.
bash, ksh, zsh
Um forro que funciona em (bash, ksh, zsh) (nem todos os shells podem fazer "expansão de chaves" na ordem inversa):
Uma alternativa que usa
eval
(que ainda é para bash, ksh, zsh e pode ser mais enigmática) é:Para entender o que acontece, substitua
eval
porecho
:O comando executado (após a expansão eval) é na verdade
echo {a..c}1 {a..c}2 {a..c}3
. Que se expande conforme você quer/precisa.todas as conchas
Existem vários shells sem "expansões de chaves", portanto, não é possível usar isso para "todos os shells". Precisamos de um loop (com um espaço em branco à direita):
Se você não deve ter nenhum espaço à direita adicionado:
Impressões
SE você precisar fazer isso para muitos valores, precisamos usar algo semelhante à expansão de chaves para gerar uma lista de números
$(seq 10)
. E, como seq não consegue gerar uma lista de letras, precisamos converter para ascii os números gerados:imprime:
As expansões de chaves
{a..c}{1..3}
são expandidas da esquerda para a direita, então você primeiro obtéma{1..3} b{1..3} c{1..3}
e, em seguida, as letras são combinadas com os números ema1 a2 a3 b1 b2 b3 c1 c2 c3
. Para obter a ordem desejada, você terá que usar a expressão um pouco mais longa acima.Usando um laço:
Isso fará um loop pela sua primeira expansão e, em seguida, expandirá cada caractere com a segunda.
Se você precisar da saída toda em uma linha, poderá remover o
\n
:Isso não lhe dará uma nova linha à direita, mas se você estiver passando para um comando ou variável, isso não deve ser um problema.
Isso funciona para o seu caso simples e pode ser estendido, mas rapidamente sairia do controle. Casos mais complexos para os quais isso não funcionaria são fáceis de construir.
Inverta a ordem das expansões de chaves e troque os caracteres:
Um método simples seria usar sort (o 1.2,1.2 significa que você pega um caractere na segunda posição e termina no mesmo lugar).
Se você quiser eles em uma linha, você pode usar tr assim:
Feito pelo método abaixo
resultado