1

Morning,

I'm currently in a situation where I have to repeat a command for several datasets and am wondering, if there is a more elegant solution than nesting loops or building a dedicated program.

So basically something like:

> echo "Hello from [NYC,Chicago] to [Berlin,Paris]"
Hello from NYC to Berlin
Hello from NYC to Paris
Hello from Chicago to Berlin
Hello from Chicago to Paris

Sure, some "for i in x,y,z"-magic would work, but that gets hard to read as soon as multiple datasets are involved.

Is there a way to easily iterate over multiple datasets in Bash? How would you solve this to keep it somewhat readable?

2 Answers 2

1

Use brace expansion.

printf '%s\n' 'Hello from '{NYC,Chicago}' to '{Berlin,Paris}

Note that it doesn't work for variables, only for literal values (as brace expansion happens before variable expansion).

1
  • Sounds just like what I was looking for - all in one place and easy to grasp. echo in my question was more of an example, but piping the output back to bash should work fine for small scripts you only use/feed with data yourself. printf '%s\n' 'iptables -A FORWARD -i '{NYC,Chicago}' -o '{Berlin,Paris} | bash
    – fbk
    Commented Mar 1, 2023 at 9:54
0

If it's a quick one-off then a brace expansion would be quick and easy. If you're looking for a programmatic variation then a couple of loops might be more suitable.

Example 1, with trivially short datasets

# Iterate until done
for colour in red green blue
do
    for shape in square triangle circle
    do
        printf "> %s - %s <\n" "$colour" "$shape"
    done
done

Example 2, with larger datasets

# Prepare the scenario with two files, "colourfile" and "shapefile"
cat >colourfile <<'X'
red
green
blue
X

cat >shapefile <<'X'
square
triangle
circle
X

# Loop until done
while IFS= read -r colour
do
    while IFS= read -r shape
    do
        printf "> %s - %s <\n" "$colour" "$shape"
    done <shapefile
done <colourfile

This will read shapefile once through for each entry in colourfile. Fortunately disk caching will help mitigate the repeated I/O. If you are really concerned then reading the inner file into an array would trade disk accesses for memory usage.

Output for both examples

> red - square <
> red - triangle <
> red - circle <
> green - square <
> green - triangle <
> green - circle <
> blue - square <
> blue - triangle <
> blue - circle <

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .