MyICQ
MyICQ

Reputation: 1158

Convert single column to multiple, ensuring column count on last line

I would like to use AWK (Windows) to convert a text file with a single column to multiple columns - the count specified in the script or on the command line.

This question has been asked before but my final data file needs to have the same column count all the way.

Example of input:

L1
L2
L3
L4
L5
L6
L7

split into 3 columns and ";" as a separator

L1;L2;L3
L4;L5;L6
L7;;        <<< here two empty fields are created after end of file, since I used just one on this line.

I tried to modify variants of the typical solution given: NR%4 {printf $0",";next} 1; and a counter, but could not quite get it right.

I would prefer not to count lines before, thereby running over the file multiple times.

Upvotes: 4

Views: 157

Answers (3)

dawg
dawg

Reputation: 104032

For an awk I would do:

awk -v n=3 '
{printf("%s%s", $0, (NR%n>0) ? ";" : ORS)}
END{
    for(i=NR%n; i<n-1; i++) printf(";")
    printf ORS
}' file 

Or, an alternative awk:

awk -v n=3 -v OFS=";" '
{ row=row ? row FS $0 : $0 }           # build row of n fields
!(NR%n) {$0=row; NF=n; print; row="" } # split the fields sep by OFS
END { if (NR%n) { $0=row; NF=n; print } }  # same
' file  

Or you can use ruby if you want more options:

ruby -le '
n=3
puts $<.read.
    split($/).
    each_slice(n).
    map{|sl| sl.fill(sl.size...n) { "" }; sl.join(";") }.
    join($\) # By using $\ and $/ with the -l the RS and ORS is set correctly for the platform
' file

Or, realize that paste is designed to do this:

paste -d';' - - - <file 

(Use a - for each column desired)

Any of those prints (with n=3):

L1;L2;L3
L4;L5;L6
L7;;

(And work correctly for other values of n...)

Upvotes: 1

anubhava
anubhava

Reputation: 785691

You may use this awk solution:

awk -v n=3 '{
   sub(/\r$/, "")   # removes DOS line break, if present
   printf "%s", $0(NR%n ? ";" : ORS)
}
END {
   # now we need to add empty columns in last record
   if (NR % n) {
      for (i=1; i < (n - (NR % n)); ++i)
         printf ";"
      print ""
   }
}' file

L1;L2;L3
L4;L5;L6
L7;;

Upvotes: 5

RavinderSingh13
RavinderSingh13

Reputation: 133680

With your shown samples please try following awk code. Using xargs + awk combination to achieve the outcome needed by OP.

xargs -n3 < Input_file | 
awk -v OFS=";" '{if(NF==1){$0=$0";;"};if(NF==2){$0=$0";"};$1=$1} 1'

Upvotes: 3

Related Questions