Reputation: 131
I have a csv file with a number of columns. I am trying to replace the second column with the second to last column from the same file. For example, if I have a file, sample.csv
1,2,3,4,5,6
a,b,c,d,e,f
g,h,i,j,k,l
I want to output:
1,5,3,4,5,6
a,e,c,d,e,f
g,k,i,j,k,l
Can anyone help me with this task? Also note that I will be discarding the last two columns afterwards with the cut function so I am open to separating the csv file to begin with so that I can replace the column in one csv file with another column from another csv file. Whichever is easier to implement. Thanks in advance for any help.
Upvotes: 3
Views: 7532
Reputation: 785156
How about this simpler awk:
awk 'BEGIN{FS=OFS=","} {$2=$(NF-1)}'1 sample.csv
EDIT: Noticed that you also want to discard last 2 columns. Use this awk one-liner:
awk 'BEGIN{FS=OFS=","} {$2=$(NF-1); NF=NF-2}'1 sample.csv
Upvotes: 11
Reputation: 46823
Pure bash solution, using IFS
in a funny way:
# Set globally the IFS, you'll see it's funny
IFS=,
while read -ra a; do
a[1]=${a[@]: -2:1}
echo "${a[*]}"
done < file.csv
Setting globally the IFS
variable is used twice: once in the read
statement so that each field is split according to a coma and in the line echo "${a[*]}"
where "${a[*]}"
will expand to the fields of the array a
separated by IFS
... which is a coma!
Another special thing: you mentionned the second to last field, and that's exactly what ${a[@]: -2:1}
will expand to (mind the space between :
and -2
), so that you don't have to count your number of fields.
Caveat. csv files need a special csv parser that is difficult to implement. This answer (and I guess all the other answers that will not use a genuine csv parser) might break if a field contains a coma, e.g.,
1,2,3,4,"a field, with a coma",5
If you want to discard the last two columns, don't use cut
, but this instead:
IFS=,
while read -ra a; do
((${#a[@]}<2)) || continue # skip if array has less than two fields
a[1]=${a[@]: -2:1}
echo "${a[*]::${#a[@]}-2}"
done < file.csv
Upvotes: 0
Reputation: 23364
In bash
while IFS=, read -r -a arr; do
arr[1]="${arr[4]}";
printf -v output "%s," "${arr[@]}";
printf "%s\n" "${output%,}";
done < sample.csv
Upvotes: 0