Help required in printing in specific format

Hi All,

I 'm matching two files based on the first 2 columns and then populate other fields along with subtraction of few fields.
I have managed to get the output. However, is there a easier way in formatting the output as shown below instead of using additional printf for getting fixed width output file?

file1:

20150731|05|0000000132|000001182401644.77
20150731|08|0000000000|000000000000000.00
20150731|09|0000026468|000001189347835.97
20150731|10|0000332300|000013254549890.91

file2:

20150731|05|0000000100|000001000000000.00
20150731|09|0000099999|000009999999999.99

Code:

awk -F'|' 'FNR==NR{a[$1,$2]=$0;next}{if(b=a[$1,$2]){print $0"|"b}}' file2 file1 | awk 'BEGIN { FS="|"; OFS = "|";OFMT = "%.2f"} {print $1,$2,$3,$4,$7,$8,($3 - $7),($4 - $8)}'

Output:

20150731|05|0000000132|000001182401644.77|0000000100|000001000000000.00|32|182401644.77
20150731|09|0000026468|000001189347835.97|0000099999|000009999999999.99|-73531|-8810652164.02

Desired output is:

20150731|05|0000000132|000001182401644.77|0000000100|000001000000000.00|+0000000032|+000000182401644.77
20150731|09|0000026468|000001189347835.97|0000099999|000009999999999.99|-0000073531|-000008810652164.02

Thanks
Shash

Here is an awk approach:-

awk -F\| '
        NR == FNR {
                A[$1 FS $2] = $0
                next
        }
        ($1 FS $2) in A {
                split(A[$1 FS $2], T)
                m = ( $3 - T[3] ); f_m = ( m < 0 ? m * -1 : m )
                n = ( $4 - T[4] ); f_n = ( n < 0 ? n * -1 : n )
                printf "%s|%s|%s|%s|%s|%s|%c%010d|%c%018.2f\n", $1, $2, $3, $4, T[3], T[4], ( m > 0 ? "+" : "-" ), f_m, ( n > 0 ? "+" : "-" ), f_n
        }
' OFS=\| file2 file1
1 Like

Bit simpler? Try

awk -F'|'  '
                {IX = $1 FS $2
                }
FNR==NR         {T3[IX] = $3
                 T4[IX] = $4
                 next
                }
IX in T3        {printf "%s|%s|%s|%+011d|%+019.2f\n", $0, T3[IX], T4[IX], $3-T3[IX], $4-T4[IX]
                }
' file2 file1
20150731|05|0000000132|000001182401644.77|0000000100|000001000000000.00|+0000000032|+000000182401644.77
20150731|09|0000026468|000001189347835.97|0000099999|000009999999999.99|-0000073531|-000008810652164.02
1 Like

Many thanks Yoda & RudiC. Both your solutions worked!

---------- Post updated at 11:58 AM ---------- Previous update was at 04:04 AM ----------

Hi RudiC,

Is there a way to have thousand separator for numeric fields?
I tried using the following code but not able to use it in the code you provided

printf "%'.2f\n" 000001182401644.77

Can you please help?

Thanks
Shash

While the single-quote-flag is discussed in e.g. my (linux) man printf it is not in FreeBSD. So its behaviour depends on the implementation.
bash (4.3.42(1)-release):

printf "%'.2f\n" 10000001182401644
10.000.001.182.401.644,00

awk:

awk 'BEGIN {printf  "%\047.2f\n", 10000001182401644}'
awk: run time error: improper conversion(number 1) in printf("%'.2f

So - you need to test what happens on your system / tool...

1 Like