1

I have a 2-line CSV file. 1 line is the header, one line is the data. This was pulled from an asset database while looking for data for just one asset. However, please note that the CSV file could conceivably contain more than just 2 lines.

I need to take the CSV (example below) and print each header entry on a separate line, with the matching data entry on the same line.

Sample CSV data

head1,head2,head3,head4
data1,data2,data3,data4

Sample output

head1   data1
head2   data2
head3   data3
head4   data4

How can this be done simply?

4 Answers 4

1
#!/bin/bash

    while { read -r line1; read -r line2; } do
       IFS=', ' read -r -a array1 <<< "$line1"
       IFS=', ' read -r -a array2 <<< "$line2"

       for index in "${!array1[@]}"
       do
           echo "${array1[index]} ${array2[index]}"
       done
    done < $1

Edited my previous answer. By nesting loops it handles more than two lines and multiple columns.

Sign up to request clarification or add additional context in comments.

Comments

0

With pure bash only:

while IFS=", " read a b c d e f g h;do echo -e "$a\t$e\n$b\t$f\n$c\t$g\n$d\t$h";done <<< $(echo $(<data.csv) )

2 Comments

That assumes static data size (number of columns, etc). Unfortunately, the number of columns is dynamic which is why I prefer the output like this.
Additionally, that assumes that we will know the number of columns ahead of time, which we won't. I have updated the original post.
0

Given that I wanted to read in from a file, I did not like the idea of output to another file which I would later have to clean up, hence I went with an associative array, which is available in BASH v4 and up only with builtin command declare -A

This will not work in BASH v3 or lower as -A is not a valid flag to the declare builtin.

Since there are known to only be 2 lines in this file, this is a fairly ugly solution that works well. It could be modified to accommodate additional lines, by adding a nested for loop within the final for loop however then you could run into other issues with line width and line wrapping, upon output.

NF=$(awk -F, 'NR==1{print NF}' temp.txt)
declare -A temparray
for ((i=1;i<=$NF;++i))
do
    temparray[0,$i]+="$(awk -v VAR=$i -F, 'NR==1{print $VAR}' temp.txt)"
done
for ((i=1;i<=$NF;++i))
do
    temparray[1,$i]+="$(awk -v VAR=$i -F, 'NR==2{print $VAR}' temp.txt)"
done
for ((i=1;i<=$NF;++i))
do
    printf "%-45s %s\n" "${temparray[0,$i]}" "${temparray[1,$i]}"
done
unset temparray

Comments

0

Using bash, this works only if you what two lines.

n=0

while read line;do echo ${line//,/\\n} > file$n ; let n++;done < L

paste file0 file1
head1   data1
head2   data2
head3   data3
head4   data4

2 Comments

This is using 2 different files as input. Not sure where that came from but I'm not splitting out the data into 2 separate files.
@Speeddymon I inserted all the data in file named L and after that I splited in twos files and used paste command

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.