How do I modify the following code so that when run in zsh it expands $things
and iterates through them one at a time?
things="one two"
for one_thing in $things; do
echo $one_thing
done
I want the output to be:
one
two
But as written above, it outputs:
one two
(I'm looking for the behavior that you get when running the above code in bash)
For loops with strings usually start at 0 and use the string's length() for the ending condition to step through the string character by character. String s = "example"; // loop through the string from 0 to length for(int i=0; i < s. length(); i++) { String ithLetter = s.
We can iterate over the array elements using the @ operator that gets all the elements in the array. Thus using the for loop we iterate over them one by one. We use the variable ${variable_name[@]} in which, the curly braces here expand the value of the variable “s” here which is an array of strings.
In order to see the behavior compatible with Bourne shell, you'd need to set the option SH_WORD_SPLIT
:
setopt shwordsplit # this can be unset by saying: unsetopt shwordsplit
things="one two"
for one_thing in $things; do
echo $one_thing
done
would produce:
one
two
However, it's recommended to use an array for producing word splitting, e.g.,
things=(one two)
for one_thing in $things; do
echo $one_thing
done
You may also want to refer to:
3.1: Why does $var where var="foo bar" not do what I expect?
Another way, which is also portable between Bourne shells (sh, bash, zsh, etc.):
things="one two"
for one_thing in $(echo $things); do
echo $one_thing
done
Or, if you don't need $things
defined as a variable:
for one_thing in one two; do
echo $one_thing
done
Using for x in y z
will instruct the shell to loop through a list of words, y, z
.
The first example uses command substitution to transform the string "one two"
into a list of words, one two
(no quotes).
The second example is the same thing without echo
.
Here's an example that doesn't work, to understand it better:
for one_thing in "one two"; do
echo $one_thing
done
Notice the quotes. This will simply print
one two
because the quotes mean the list has a single item, one two
.
You can use the z
variable expansion flag to do word splitting on a variable
things="one two"
for one_thing in ${(z)things}; do
echo $one_thing
done
Read more about this and other variable flags in man zshexpn
, under "Parameter Expansion Flags."
You can assume the Internal Field Separator (IFS) on bash to be \x20 (space). This makes the following work:
#IFS=$'\x20'
#things=(one two) #array
things="one two" #string version
for thing in ${things[@]}
do
echo $thing
done
With this in mind you can implement this in many different ways just manipulating the IFS; even on multi-line strings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With