0

I am writing bash script for first time . I have to use nested for loop. I have an array like this:

(foo,bar a,b)

There are two elements in the array and each element in array is separated by commas. I want each element in array to split and print each element. The final result I want is

foo
bar
a
b

I am using nested for loop as below but I am not getting any response

    IFS=','
    echo "class names is::${classNames[@]}" // prints foo,bar a,b
    for ((n=0;n<${#classNames[@]};n++)){
    
    classes=${classNames[n]}
    
    for ((i=0;n<${#classes[@]};i++)){
    
    echo "${eachClass[i]}"
    
    }
    }
2
  • IFS=',' aaaand where does IFS count? Commented Feb 10, 2021 at 10:21
  • So IFS should be a space or a comma? Commented Feb 10, 2021 at 10:25

3 Answers 3

2

You could:

arr=(foo,bar a,b)
for i in "${arr[@]}"; do
   while IFS=, read -ra arr_in; do
       for j in "${arr_in[@]}"; do
           echo "$j"
       done
   done <<<"$i"
done

or like:

for i in "${arr[@]}"; do
   readarray -d, -t arr_in < <(printf "%s" "$i")
   for j in "${arr_in[@]}"; do
       echo "$j"
   done
done

or just:

while IFS=, read -ra arr_in; do
    for j in "${arr_in[@]}"; do
       echo "$j"
    done
done < <(printf "%s\n" "${arr[@]}"

or even:

while IFS=, read -ra arr_in; do
    printf "%s\n" "${arr_in[@]}"
done < <(printf "%s\n" "${arr[@]}"

but that said:

printf "%s\n" "${arr[@]}" | tr ',' '\n'

will also print the same.

Do not use { } as loop terminators - it's undocumented very old bash/shell syntax. Use do..done.

classes=... is a normal variable, not an array, and in such assignment IFS does not matter - here the right part of = is not word splitted. To assign an array, use braces classes=(${classNames[n]}).

You could just split the values on spaces and comma with IFS:

IFS=', ' read -ra arr <<<"${arr[*]}"
for i in "${arr[@]}"; do
    echo "$i"
done

or even like:

while IFS= read -r i; do
    echo "$i"
done < <(IFS=', '; printf "%s\n" ${arr[*]})
Sign up to request clarification or add additional context in comments.

Comments

1

... or like this

for item in "${arr[@]}"; {
    sub=(${item//,/ })
    echo "item1=${sub[0]}"
    echo "item2=${sub[1]}"
}

with read

for item in "${arr[@]}"; {
    read i1 i2 <<< ${item//,/ }
    echo "item1=$i1"
    echo "item2=$i2"
}

The trick is that we switch ',' to ' '(space) via this bash syntax ${item//,/ }(${var_name//pattern/replacement}) this is called variable substitution. And this one <<< is used to read directly from var.

1 Comment

can you please explain what is role of //,/ and <<< in bash and what are they called in bash.
0

A practical one-liner solution without using an apparent loop is

(IFS=', '; printf '%s\n' ${classNames[*]})

It runs in a subshell not to mess up with current shell's IFS.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.