Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transform table into 2 columns

Tags:

linux

bash

awk

How do i transform table like this:

1   0.75    1   0.38
2   0.80    2   0.18

to something like:

1   0.75
2   0.80
1   0.38
2   0.18

The coloumn separated by a tab character or comma.

I want to do it in linux bash, with any number of colounm and rows. I tried to do it with awk but didn't find the right way.

Thanks

like image 270
Ravid Avatar asked May 13 '18 14:05

Ravid


2 Answers

Using cut, with comma delimiters:

cut -d, -f1-2 input > output && cut -d, -f3-4 input >> output

input:

1,0.75,1,0.38
2,0.80,2,0.18

output:

1,0.75
2,0.80
1,0.38
2,0.18

For tab delimited file use: cut -d$'\t' ...

This is two pass but uses constant memory. Easy to extend to any number of columns.

If you don't mind the order you can just do:

sed 's/\([^,]*,[^,]*\),/\1\n/' input
like image 65
perreal Avatar answered Oct 17 '22 10:10

perreal


Here is one in awk:

$ awk '
BEGIN{ FS=OFS="\t" }                                        # tab-delimited
NR==1{ nf=NF }                                              # get field count 
{
    for(i=1;i<nf;i+=2)                                      # iterate every other field
        if(i==1)                                            # print first 2 fields
            print $1,$2
        else                                                # buffer others
            b[i]=b[i] sprintf("%s" OFS "%s" ORS,$i,$(i+1))
}
END {                                                       # in the end
    for(i=3;i<nf;i+=2)                                      # iterate buffers
        printf "%s",b[i]                                    # and output
}' file
1       0.75
2       0.80
1       0.38
2       0.18

Edit: An awk-sort-cut hybrid:

$ awk '                   # awk to add field number to output
BEGIN { FS=OFS="\t" }     # tab-delimiter
{
    for(i=1;i<NF;i+=2)    # iterate fields
        print i,$i,$(i+1) # print field number and data fields
}' file |
sort -s -t $'\t' -k1n |   # sort on the first field only
cut -f 2-
1       0.75
2       0.80
1       0.38
2       0.18
like image 40
James Brown Avatar answered Oct 17 '22 09:10

James Brown