3

I am running a script in a loop which creates some data as per some logic and then displays output in some combination but the output I am getting is in new line

Roll number               : 187437366 
Mobile Number             : 07995036927
Grade                     : A
Roll number               : 187437367 
Mobile Number             : 07995036937
Grade                     : B

However I want output in a tabular format something like below -

Roll Number | Mobile Number | Grade
187437366   | 07995036927   | A
187437466   | 07995037922   | A2
187437266   | 07995036921   | B
187437766   | 07995036120   | C

I am unable to find a concept on how to achieve this...can someone help me please?

1
  • 1
    Please edit your question to fix it such that the provided expected output is exactly what you'd expect given the provided sample input.
    – Ed Morton
    Feb 17, 2020 at 21:40

4 Answers 4

1

One liner:

$ awk -F':' '{printf "%s%s", $2, (/^Grade/)?"\n":"\t|"}' file

Output:

 187437366      | 07995036927   | A
 187437367      | 07995036937   | B
1

awk is not the only tool in the toolbox, of course. Just to counterbalance the inevitable deluge of awk scripts, here's Miller in action:

% mlr --ixtab --ips : --opprint cat << END
Roll number               : 187437366
Mobile Number             : 07995036927
Grade                     : A

Roll number               : 187437367
Mobile Number             : 07995036937
Grade                     : B

END
Roll number                Mobile Number              Grade
 187437366                  07995036927                A
 187437367                  07995036937                B
%

Just make your script emit a blank line after every record, or add in an intermediary filter that does that, and what you have is in the "XTAB" input format, with : as the "pair separator" character (c.f. the --ixtab and --ips options).

The aforegiven is the "PPRINT" output format. For output more like the question, there's a --barred option for "PPRINT" and a "Markdown" alternative output format with --omd. However, I do not have a recent version of Miller immediately to hand for demonstration.

1
  • FWIW, just so we're comparing apples to apples and in case it is an option: If there were a blank line between every iteration then there would be a much briefer/simpler awk solution possible too by putting awk in paragraph mode with RS="" and using FS="[:\n]" as the field separator. Then every odd numbered field is the header string and every even numbered one is the associated value.
    – Ed Morton
    Feb 17, 2020 at 22:27
0

Using awk and tabs and | as separators:

awk -F: '
  BEGIN{ printf "%s\t|%s\t|%s","Roll Number","Mobile Number","Grade"}
  { gsub(/ /,"",$2); printf "%s", ($1 ~ "^Roll" ? RS : "\t|") $2 }
  END { print "" }
' file

In the BEGIN block, print the header using a tab and | between each field.
Then remove all space characters from the second field (leading and trailing) and

  1. if the first field begins with Roll, add a record separator RS (newline), otherwise print a tab and |
  2. print the second field

In the END block, print another newline.

Output:

Roll Number     |Mobile Number  |Grade
187437366       |07995036927    |A
187437367       |07995036937    |B
2
  • Hi, I am getting output like below Roll Number |Mobile Number |Grades |187437435 07410000911 |A |187437436 07410000912 |A+ |187437437 07410000913 |B
    – anurag
    Feb 17, 2020 at 18:07
  • It's hard to read output from the comments. Are you sure your input file is a unix text file and doesn't contain carriage returns? Do you get the same output if you run dos2unix file and run the command again?
    – Freddy
    Feb 17, 2020 at 18:24
0

Without coupling your code to any of the data values in your input file and instead just relying on your header values repeating:

$ cat tst.awk
BEGIN {
    FS = "[[:space:]]*:[[:space:]]*"
    OFS = "|"
}
seen[$1]++ { prt() }
{
    hdrs[++numFlds] = $1
    vals[numFlds] = $2
}
END { prt() }

function prt(   fldNr) {
    if ( !doneHdr++ ) {
        for (fldNr=1; fldNr<=numFlds; fldNr++) {
            printf "%s%s", hdrs[fldNr], (fldNr<numFlds ? OFS : ORS)
        }
    }
    for (fldNr=1; fldNr<=numFlds; fldNr++) {
        printf "%s%s", vals[fldNr], (fldNr<numFlds ? OFS : ORS)
    }
    numFlds = 0
    delete seen
}

.

$ awk -f tst.awk file | column -s'|' -o' | ' -t
Roll number | Mobile Number | Grade
187437366   | 07995036927   | A
187437367   | 07995036937   | B

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .