0

How do I get the following z shell script to function the same way that it would in bash?

for x in {f..k}
    do echo ${x}
done

In bash I get f j k printed out but in zsh, I get {f..k} printed literally.

EDIT

What I'm actually trying to do (should have mentioned this initially) is:

FIRSTLETTER=a
LASTLETTER=b
for x in {$FIRSTLETTER..$LASTLETTER}
do 
    echo "/dev/sd${x}1"
done
  • `bash` is the shell that expands `{$FIRSTLETTER..$LASTLETTER}` to `{a..b}`; `zsh` should correctly expand it to `a b`. – chepner Nov 08 '18 at 21:07
  • duplicate: https://stackoverflow.com/questions/2394728/zsh-brace-expansion-seq-for-character-lists-how – scinart Nov 09 '18 at 05:40

3 Answers3

1

It works:

for x ({f..k}); echo ${x}
scinart
  • 457
  • 2
  • 9
1

In bash, brace expansion happens before parameter expansion. The result is that {$FIRSTLETTER..$LASTLETTER} isn't subject to brace expansion, because it's not a valid sequence expression:

A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or single characters

Only then does the literal string undergo parameter expansion, resulting in the single word {a..b}.

In zsh, brace expansion occurs after several other types of expansion, include parameter expansion, have occurred. Thus, {$FIRST_LETTER..$LAST_LETTER} expands to {a..b}, which then undergoes brace expansion to produce a b.

The end result is that what you are doing should work in zsh, but not in bash. Further, short of using eval, there is no way to do what you want in bash.

for x in $(eval "echo {$FIRSTLETTER..$LASTLETTER}")

Keep in mind that this is fragile, and requires you to be very sure that the two parameters can only expand to single letters each.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

No zsh handy, just trying a workaround. Will it do this?

for o in $(seq 102 107)
do x=$(printf %x $o)
   printf "\x$x"
done
Paul Hodges
  • 13,382
  • 1
  • 17
  • 36