Home > front end >  AWK: convert single column to multiple, ensuring column count on last line
AWK: convert single column to multiple, ensuring column count on last line

Time:01-07

I would like using AWK (Windows) to convert a text file with a single column to multiple columns - count specified in script or on 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 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.

CodePudding user response:

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;;

CodePudding user response:

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'

CodePudding user response:

Using any awk:

$ awk -v n=3 -v OFS=';' '
    { rec=rec sep $0; sep=OFS }
    !(NR%n) { print rec; rec=sep="" }
    END { if (NR%n) { $0=rec; NF=n; print } }
' file
L1;L2;L3
L4;L5;L6
L7;;

That above uses Unix quoting, you'd have to figure out the Windows equivalent for yourself or store the script in a file.

CodePudding user response:

paste is designed to do this:

paste -d';' - - - <file 

For an awk I would do:

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

Or you can use ruby:

ruby -e '
row=3
puts $<.read.
        split(/\r?\n/).
        each_slice(row).
        map{|sl| sl.fill(sl.size...row) { "" }; sl.join(";") }.
        join("\n") # "\r\n" for Windows
' file

Any of those prints:

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