calandoa
calandoa

Reputation: 6147

How can I generate a list with brace expansion in a specific order?

I know how to easily generate a list this way :

echo {a,b,c,d}_{0..3}

which will give:

a_0 a_1 a_2 a_3 b_0 b_1 b_2 b_3 c_0 c_1 c_2 c_3 d_0 d_1 d_2 d_3

But how to generate the same list, but with the second brace being expended with an higher priority, to obtain this? :

a_0 b_0 c_0 d_0 a_1 b_1 c_1 d_1 a_2 b_2 c_2 d_2 a_3 b_3 c_3 d_3

Any trick like sorting from the end, or from character n is OK, as long as it fits on one line. I am also using zsh, but something working with bash is fine.

Upvotes: 6

Views: 534

Answers (5)

Dieter
Dieter

Reputation: 26

eval echo \{a..d\}_{0..3}

is enough

The first expansion -- by the shell -- is to

{a..d}_0 {a..d}_1 {a..d}_2 {a..d}_3

the second expansion by eval is then

a_0 b_0 c_0 d_0 a_1 b_1 c_1 d_1 a_2 b_2 c_2 d_2 a_3 b_3 c_3 d_3

The result is sent to stdout.

Upvotes: 0

calandoa
calandoa

Reputation: 6147

I also found an other solution (zsh only), needlessly complex and therefore interesting:

print {a,b,c,d}_${^=${$+0 1 2 3}}

What is doing zsh here? It starts with last nested brace and:

  • check if $$ exist, so use "0 1 2 3" (operator +)
  • split it into an array (operator =)
  • apply distribution of each element to the string, like brace expansion (operator ^)
  • finally apply expansion of the first brace (because of the lower priority of brace expansion compared to parameter expansion)

Note that I must expand {0..3} myself, as no flag/operator can trigger a preliminary expansion of this kind AFAIK (except eval as explained above).

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 247042

Not strictly bash-in-house, but

printf "%s\n" {a,b,c,d}_{0..3} | sort -t_ -k2,2n

Upvotes: 2

Alfe
Alfe

Reputation: 59526

I'd like to add another approach solving this issue with a different hack. It's based on turning the expression, evaluating it then, then turning the result back again:

eval echo $(echo '{a,b,c,d}_{0..3}' | rev | tr '{}' '}{') | rev

results in

a_0 b_0 c_0 d_0 a_1 b_1 c_1 d_1 a_2 b_2 c_2 d_2 a_3 b_3 c_3 d_3

But I'm not sure I can really propose to do this ;-)

Upvotes: 2

Alfe
Alfe

Reputation: 59526

That's not implemented, but you could use an ugly hack like

echo $(eval echo \{a,b,c,d\}_{0..3})

to achieve it by actively first evaluating the latter brace and in the second step the first brace.

Keep in mind though that the intermediate step must be small enough to be still parsable by the shell ;-)

Upvotes: 7

Related Questions