From the text you downloaded, it looks like you ignored my post #11 in this thread. I have made several changes from the script I supplied in that post to meet your new requirements:
- Since the output format you say you want for account/name subtotals and account totals doesn't match the sample output you have shown us in post #12 in this thread, I have made up my own formats for these lines that I hope will be something you can use.
- This version of the script sorts the entire input file before calling
awk
and prints account/name subtotals and account totals as data is read (instead of reading your unsorted data, sorting just the keys, and printing everything at the end).
- This version does not make any attempt to line up output columns (since the sample output you said you want is not aligned in any way.
- This version prints the account number on account number total lines as requested and prints the account number and name subtotal lines.
- This version uses OFMT as requested (but uses
%.2f
instead of the default %6g
since the sample data you downloaded has all values in the data fields presented with two digits after the decimal point).
- This version accepts a single file operand to name the input file. If called with no operands, it will default to using a file named
file
.
- As long as the number of fields is constant within your input file, this version can handle any number of input fields.
Hopefully, this will produce something closer to what you want:
#!/bin/ksh
# Sort input file (default to "file" if no parameters are given) by (numeric)
# account number and (alphanumeric) account name.
sort -t'|' -k1,1n -k2,2 "${1:-file}" |
awk -F'|' ' # Use awk to evaluate the following wcript with FS (the input
# field separator) set to "|".
# Define function to print account number/account name subtotals and account
# number totals.
function pt(level, i) {
# Print account number/account name subtotal header.
printf("%d%s%s%sTotal%s", acno, OFS, name, OFS, OFS)
# Print account/name subtotals, add subtotals to account totals, and
# clear subtotals in preparation for next name.
for(i = 4; i <= nf; i++) {
printf(OFMT "%s", s, (i == nf) ? RS : OFS)
t += s
s = 0
}
if(level) {
# Print account totals too.
# Print account total header.
printf("%d%s-%sACNO Total%s", acno, OFS, OFS, OFS)
# Print account totals and clear in preparation for next
# account.
for(i = 4; i <= nf; i++) {
printf(OFMT "%s", t, (i == nf) ? RS : OFS)
t = 0
}
}
}
# Set defaults before reading the first line form the sorted input file.
BEGIN { # Change default sum output format to 2 decimal places.
OFMT = "%.2f"
# Set output field separator to match input field separator.
OFS = FS
}
FNR == 1 {
# Grab the field count from the 1st input line.
nf = NF
# Grab account # and name from the 1st input line.
acno = $1
name = $2
}
{ # Process a line from our sorted input file.
if(acno != $1) {
# The account number has changed; print last account number/
# account name subtotals and account number totals.
pt(1)
# Grab new account number and account names from this line.
acno = $1
name = $2
}
if(name != $2) {
# If the account name has changed (but the account number is the
# same), print account number/account name subtotals.
pt(0)
# Grab the account name from this line.
name = $2
}
# Add current line data to account name subtotals.
for(i = 4; i <= nf; i++)
s += $i
}
1 # Print the current line.
END { # Print the total line for the last account name and account number.
pt(1)
}' # End the awk script.
If a file named file
contains the sample data you provided in post #1 in this thread and you invoke it as:
./scriptname
it produces the output:
1000|ADU|CAN|10|20|30|40
1000|ADU|CAN|10|20|30|40
1000|ADU|Total|20.00|40.00|60.00|80.00
1000|NADU|CAN|10|20|30|40
1000|NADU|CAN|10|20|30|40
1000|NADU|Total|20.00|40.00|60.00|80.00
1000|-|ACNO Total|40.00|80.00|120.00|160.00
1001|AND|NAC|20|70|20|10
1001|AND|NAC|40|50|40|50
1001|AND|Total|60.00|120.00|60.00|60.00
1001|PAND|NAC|20|70|20|10
1001|PAND|NAC|40|50|40|50
1001|PAND|Total|60.00|120.00|60.00|60.00
1001|-|ACNO Total|120.00|240.00|120.00|120.00
1005|ANDP|ACN|20|10|30|40
1005|ANDP|ACN|20|50|10|30
1005|ANDP|Total|40.00|60.00|40.00|70.00
1005|-|ACNO Total|40.00|60.00|40.00|70.00
and, if you invoke it as:
./scriptname file2
where file2
is a file containing the data you downloaded with your post #12 (with DOS <carriage-return> characters removed and a <newline> character added to terminate the last line in your input file), it produces the output:
1000|ADU|CAN|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1000|ADU|CAN|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1000|ADU|Total|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12
1000|NADU|CAN|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1000|NADU|CAN|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1000|NADU|Total|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12
1000|-|ACNO Total|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24
1001|AND|NAC|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1001|AND|NAC|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1001|AND|Total|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12
1001|PAND|NAC|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1001|PAND|NAC|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1001|PAND|Total|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12
1001|-|ACNO Total|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24|501362.24|498342.24|506194.24
1005|ANDP|ACN|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1005|ANDP|ACN|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56|125340.56|124585.56|126548.56
1005|ANDP|Total|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12
1005|-|ACNO Total|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12|250681.12|249171.12|253097.12