#!/bin/awk -f # see http://theunixshell.blogspot.de/2014/05/comparing-two-files-using-awk.html BEGIN { if(ARGC != 3) { printf("Usage: %s company_file balance_file\n", ARGV[0]) exit 2 } # split on dollar sign for easier processing of second file FS = "$" } # Sanitize and filter input first # We use the NR == FNR idiom to distinguish the two files # We are also very forgiving when it comes to company names. They just have # to start with a non-whitespace and cannot contain dollar signs (NR == FNR && ! /^[^\s\$][^$]*$/) || (NR != FNR && ! /^[^\s\$][^$]*\s+\$[[:digit:]]+\.[[:digit:]]{2}\s+((due)|(payment))$/) { printf("Formatting error in file '%s', line %d: '%s'\n", FILENAME, FNR, $0) > "/dev/stderr" next } # both files: Retrieve name of company by removing trailing whitespace { company = gensub(/\s+$/, "", 1, $1) } # company_file: Initializes balance array in case a company made no entries in # the balance file. # Aborts processing of this line at the end so that we don't have to check for # NR != FNR in the rest of the script NR == FNR { balance[company] = 0. next } # balance_file: Retrieve amount of money. # Note that $2 contains everything up to the end of the file but strtonum will # abort without error on the first non-digit # We also check for companies not defined in company_file and skip them { money = strtonum($2) if(! company in balance) { printf("Undefined company '%s' in file '%s', line '%d'\n", company, FILENAME, FNR) > "/dev/stderr" next } } # add or subtract money depending on instruction /due$/ { balance[company] -= money } /payment$/ { balance[company] += money } # print balance END { for (company in balance) printf("%s\t$%.2f\n", company, balance[company]) }