1

I am trying to write different arrays into a csv file ($file) columns.
Each array has the same number of values. For example, arr1 and arr2 have 3 values each

arr1=( 23 45 34 )
arr2=( "abc,d"  ef  g )

I tried the following code but I'm getting the wrong results

for i in "${!arr1[@]}"; do
echo  "${arr1[i]}, ${arr2[i]}"  >> $file
done

I'm getting the following where col1, col2 and col3 are 3 columns.

col1    col2    col3
23      "abc    d"
45       ef 
34       g

but the desired result is

col1    col2   
23      "abc,d"
45       ef 
34       g

It seems like the embedded coma in "abc,d" creates a problem. Anyone knows a way around this or any better way to do this?

Thank you in advance!

1
  • Note that $file needs to be defined... Jul 7, 2021 at 1:32

2 Answers 2

1

It's not clear from your question exactly how you are looking at the file (perhaps with a spreadsheet program?) however the shell is likely stripping off the quotes in your array definition: if you want embedded commas to be handled in a CSV-complient way, you should add them as literal quotes ex.

arr1=( 23 45 34 )
arr2=( \"abc,d\"  ef  g )

so that the shell's internal representation looks like

$ declare -p arr1 arr2
declare -a arr1=([0]="23" [1]="45" [2]="34")
declare -a arr2=([0]="\"abc,d\"" [1]="ef" [2]="g")

Then for example

for i in "${!arr1[@]}"; do 
  printf '%s,%s\n' "${arr1[i]}" "${arr2[i]}"
done > "$file"

results in

$ cat "$file"
23,"abc,d"
45,ef
34,g

Another option is to quote all fields ex.

arr1=( 23 45 34 )
arr2=( "abc,d"  ef  g )

for i in "${!arr1[@]}"; do 
  printf '"%s","%s"\n' "${arr1[i]}" "${arr2[i]}"
done > "$file"

giving

$ cat "$file"
"23","abc,d"
"45","ef"
"34","g"
0
0

This answer assumes that your data contains no literal tabs.

Start by creating a simple column for each array (with header), and combine them using paste, creating a TSV data stream:

#!/bin/bash

arr1=( 23 45 34 )
arr2=( abc,d ef g )

paste <( echo col1; printf '%s\n' "${arr1[@]}" ) \
      <( echo col2; printf '%s\n' "${arr2[@]}" )

The output of this will read

col1    col2
23      abc,d
45      ef
34      g

You can then use Miller to convert it into properly quoted CSV:

#!/bin/bash

arr1=( 23 45 34 )
arr2=( abc,d ef g )

paste <( echo col1; printf '%s\n' "${arr1[@]}" ) \
      <( echo col2; printf '%s\n' "${arr2[@]}" ) | mlr --t2c cat

This would generate

col1,col2
23,"abc,d"
45,ef
34,g

... which a CSV-aware program would read as

col1 col2
23 abc,d
45 ef
34 g

A CSV-aware spreadsheet program would likely also be able to read that TSV data, so Miller would not be strictly needed.

You must log in to answer this question.

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