2

Trying to have a multiple variable follow another variable, but I'm not getting 7 different VOL variables.

NME=(Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1)
VOL=/Volumes/${NME}

for Copy in $VOL ; do
    echo $Copy
done
ams
  • 5,807
  • 1
  • 20
  • 27
Phil
  • 65

1 Answers1

2

In zsh (since you seem to be using zsh syntax), you'd do:

nme=(Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1)
vol=(/Volumes/$^nme)
for Copy in $vol; do
  printf '%s\n' $Copy
done

Without the ^, /Volumes/$nme would be the concatenation of /Volumes/ with the values of the array so only the first element would have /Volumes/ prepended to it.

Or, when assigning to a scalar variable instead of an array variable, like you did, it would be /Volumes/ concatenated with the array elements joined with the first character of $IFS.

(note that the behaviour would be different in ksh or bash, where $nme is just short for ${nme[0]}).

Adding the ^ in $^nme allows the concatenation to be distributed to each element of the array.

That ^ is reminiscent of rc's ^ (non-)operator and possibly explains the origin of that ^ zsh variable expansion operator. In rc:

nme=(Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1)
vol=(/Volumes/^$nme)
for (Copy in $vol) printf '%s\n' $Copy

That ^ is not needed. vol=(/Volumes/$nme) would work just the same. The point here is that rc does distribute the concatenation. However ^ (which is just ignored and discarded) can be seen as a concatenation operator because it facilitates things like $nme^2 ($nme2 would be treated as the nme2 variable, you'd need to write it $'nme'2 otherwise).

In bash (also works in zsh):

nme=(Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1)
vol=("${nme[@]/#//Volumes/}")
for Copy in "${vol[@]}"; do
  printf '%s\n' "$Copy"
done

Here, we're using the parameter leading pattern substitution operator (${param/#pattern/replacement}) applied to each element of the array. Here, we're replacing the empty string at the start of each element with /Volumes/).

While that syntax comes from ksh93, it doesn't work in ksh93 as it doesn't like that empty pattern. There, you need to replace ${nme[@]/#//Volumes/} above with ${nme[@]/#@()//Volumes/} for instance. @() being an empty group.

Of course, in standard sh syntax, you can always do:

set Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1
for Copy do
  printf '/Volumes/%s\n' "$Copy"
done

or:

set Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1
for Copy do
  Copy=/Volumes/$Copy
  printf '%s\n' "$Copy"
done

Or if assuming your echo (you should really get used to using printf instead) was not just a place holder and all you want to do is display those one per line:

set Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1
printf '/Volumes/%s\n' "$@"

Or:

printf '/Volumes/%s\n' Y6T1 Y6-T1 Y6.T1 Yr6T1 Yr6-T1 Yr6.T1 Yr6Term1
  • what does rc's ^ do? i sometimes get tripped up in zsh on ^ and never bothered to find out why. the problem usually happens when i screw up my terminal and need stty sane erase ^H. also, probably you skipped it because its not really about variables, but it might be the asker just wants printf /Volumes/%s\\n 1 2 3 4 5. people sometimes go out of their way to put stuff in variables, i think. – mikeserv Oct 28 '15 at 12:39
  • 1
    @mikeserv In rc, ^ is more like a non-operator. It's ignored but facilitates $var^something which you'd have to be write $'var'something otherwise. It's just that in rc, x$array (or x^$array) and $'array'x (or $array^x), where array=(a b), expand to xa xb and ax bx instead of xa b or a bx. In zsh, $^array enables a similar behaviour (it's different for $a^$b in rc vs $^a$^b in zsh though). In zsh, ^ is an extendedglob negation operator. In the Bourne shell, ^ is another name for |. – Stéphane Chazelas Oct 28 '15 at 12:57