Como gerar seqüências de caracteres separadas por vírgula usando expansão bash brace

17

eu gostaria

$ echo a{b,c,d}

para produzir uma lista separada por vírgula como

ab,ac,ad

em vez da saída usual

ab ac ad

Qual é a maneira mais fácil de fazer isso na linha de comando?

jrennie
fonte

Respostas:

9

Supondo que os elementos não contenham espaços, você pode converter espaços em vírgulas:

echo a{b,c,d} | tr ' ' ,

que produz:

ab,ac,ad

Você também pode usar intervalos com caracteres:

echo a{b..d} | tr ' ' ,

Isso é especialmente útil se você deseja um alcance maior.

devnull
fonte
13

Parece que o bash não usa $ IFS para juntar as palavras geradas. Outra técnica seria armazenar as palavras geradas em uma matriz e, em seguida, $ IFS estará em jogo:

Vou usar um subshell para não alterar o IFS desse shell: escolha um dos

( words=( a{b,c,d} ); IFS=,; echo "${words[*]}" )
( set -- a{b,c,d}; IFS=,; echo "$*" )

Isso emite a string separada por vírgula para stdout. Se você deseja capturá-lo:

joined=$( set -- a{b,c,d}; IFS=,; echo "$*" )
Glenn Jackman
fonte
Ele não une as palavras geradas. Esse é o ponto, ele se expande para separar palavras.
Stéphane Chazelas
5

Estou certo de que há muitas maneiras de conseguir isso. Aqui está um método:

echo a{b,c,d} | sed 's/ /,/g'
Timothy Martin
fonte
2

Expanda os elementos como você mostrou e faça um loop sobre eles, adicionando a vírgula a todos, exceto a primeira iteração:

for i in a{b,c,d}; do
  u="${u:+$u, }$i"
done
echo "$u"

Resultado:

ab, ac, ad

Consulte substituição de parâmetros bash .

Marki
fonte
1

Aqui está uma solução apenas para o bash.

(IN=$(echo a{b,c,d}); echo ${IN// /,})
# ab,ac,ad

A parte antes do ponto e vírgula é atribuída ab ac adà variável INe a segunda parte usa a pesquisa e a substituição para alterar todos os espaços por vírgulas. O //significa todos os jogos, não apenas o primeiro.

Faça tudo em uma subshell (os parênteses) para não poluir seu espaço para nome.

erg
fonte
1

Vale a pena notar que, em muitos contextos, uma vírgula à direita é aceitável nessa lista. IF uma vírgula de fuga é aceitável, a maneira mais fácil de manusear a substituição é printf:

some-command "$(printf %s, a{b,c,d} )"

(Onde some-commandestá um comando que é executado em uma lista separada por vírgula e não se importa com uma vírgula à direita.)

Na verdade, mesmo que você não deva ter uma vírgula, você pode usar printf; você só precisa especificar o número de argumentos que espera, o que o torna mais desajeitado para listas muito longas:

some-command "$(printf %s,%s,%s a{b,c,d} )"
Curinga
fonte