stephen
stephen

Reputation: 31

Convert single column into three comma separated columns using awk

I have a single long column and want to reformat it into three comma separated columns, as indicated below, using awk or any Unix tool.

Input:

Xaa
Ybb
Mdd
Tmmn
UUnx
THM
THSS
THEY
DDe

Output:

Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe

Upvotes: 3

Views: 219

Answers (3)

John1024
John1024

Reputation: 113844

$ awk '{printf "%s%s",$0,NR%3?",":"\n";}' file
Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe

How it works

For every line of input, this prints the line followed by, depending on the line number, either a comma or a newline.

The key part is this ternary statement:

NR%3?",":"\n"

This takes the line number modulo 3. If that is non-zero, then it returns a comma. If it is zero, it returns a newline character.

Handling files that end before the final line is complete

The assumes that the number of lines in the file is an integer multiple of three. If it isn't, then we probably want to assure that the last line has a newline. This can be done, as Jonathan Leffler suggests, using:

awk '{printf "%s%s",$0,NR%3?",":"\n";} END { if (NR%3 != 0) print ""}' file

If the final line is short of three columns, the above code will leave a trailing comma on the line. This may or may not be a problem. If we do not want the final comma, then use:

awk 'NR==1{printf "%s",$0; next} {printf "%s%s",(NR-1)%3?",":"\n",$0;} END {print ""}' file

Jonathan Leffler offers this slightly simpler alternative to achieve the same goal:

awk '{ printf("%s%s", pad, $1); pad = (NR%3 == 0) ? "\n" : "," } END { print "" }'

Improved portability

To support platforms which don't use \n as the line terminator, Ed Morton suggests:

awk -v OFS=, '{ printf("%s%s", pad, $1); pad = (NR%3?OFS:ORS)} END { print "" }' file

Upvotes: 7

karakfa
karakfa

Reputation: 67507

There is a tool for this. Use pr

pr -3ats,

3 columns width, across, suppress header, comma as separator.

Upvotes: 3

slitvinov
slitvinov

Reputation: 5768

xargs -n3 < file | awk -v OFS="," '{$1=$1} 1'

xargs uses echo as default action, $1=$1 forces rebuild of $0.

Using only awk I would go with this (which is similar to what proposed by @jonathan-leffler and @John1024)

{
     sep = NR == 1 ? ""   : \
          (NR-1)%3 ? ","  : \
                     "\n"
     printf sep $0
}

END {
     printf "\n"
}

Upvotes: 0

Related Questions