mirror of
https://github.com/simonmichael/hledger.git
synced 2024-12-25 03:13:25 +03:00
feat: bin: Add AWK script to sort postings and merge duplicates
Co-authored-by: Murukesh Mohanan <murukesh.mohanan@gmail.com>
This commit is contained in:
parent
0a052c7aef
commit
1f088324c6
96
bin/sortandmergepostings
Executable file
96
bin/sortandmergepostings
Executable file
@ -0,0 +1,96 @@
|
||||
#!/usr/bin/awk -f
|
||||
# Script adapted from suggestions on https://unix.stackexchange.com/a/527004/1925
|
||||
#
|
||||
# Passed a ledger file, this will:
|
||||
# 1. Sort accretion postings before deductions
|
||||
# 2. Sort postings by account alphabetically
|
||||
# 3. Merge 1 set of postings with the same account and direction by clearing
|
||||
# the amount field. Note all posting meta data must also match to merge.
|
||||
#
|
||||
# Suggested usage:
|
||||
# $ sortandmergepostings journal.ledger | hledger -f - print -x
|
||||
#
|
||||
# Given that each run will only merge and recalculate amounts on one account per
|
||||
# transaction it may need to be run multiple times to fully normalize a ledger.
|
||||
|
||||
BEGIN { FS = "[[:space:]][[:space:]]+" }
|
||||
|
||||
function dump() {
|
||||
an = asorti(accretions, as)
|
||||
dn = asorti(deductions, ds)
|
||||
for (i=1; i<=an; i++) {
|
||||
postings[length(postings)+1] = accretions[as[i]]
|
||||
}
|
||||
for (i=1; i<=dn; i++) {
|
||||
postings[length(postings)+1] = deductions[ds[i]]
|
||||
}
|
||||
for (i in postings) {
|
||||
posting = postings[i]
|
||||
split(posting, parts, FS)
|
||||
currency = parts[3]
|
||||
gsub(/[[:digit:]., ]+/, "", currency)
|
||||
if (!inferred && (!merge || merge == parts[2]) && seen[parts[2] currency parts[4]]>1 && parts[3] !~ /@/) {
|
||||
if (!merge) merged[i] = " " parts[2] " " parts[4]
|
||||
merge = parts[2]
|
||||
} else {
|
||||
merged[i] = posting
|
||||
}
|
||||
}
|
||||
for (i in merged) print merged[i]
|
||||
if (inferred) print inferred
|
||||
inferred = ""
|
||||
merge = ""
|
||||
delete accretions
|
||||
delete deductions
|
||||
delete postings
|
||||
delete merged
|
||||
delete seen
|
||||
}
|
||||
|
||||
!NF {
|
||||
dump()
|
||||
print
|
||||
next
|
||||
}
|
||||
|
||||
END {
|
||||
dump()
|
||||
}
|
||||
|
||||
/^[^[:space:]]/ {
|
||||
dump()
|
||||
print $0
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
postingct++
|
||||
account = $2
|
||||
amount = $3
|
||||
comments = $4
|
||||
currency = amount
|
||||
gsub(/[[:digit:]., ]+/, "", currency)
|
||||
sub(/^[*!] /, "", account)
|
||||
}
|
||||
|
||||
account ~ /^;/ {
|
||||
print
|
||||
next
|
||||
}
|
||||
|
||||
!amount {
|
||||
inferred = $0
|
||||
next
|
||||
}
|
||||
|
||||
amount !~ /@/ {
|
||||
seen[account currency comments]++
|
||||
}
|
||||
|
||||
amount !~ /-/ {
|
||||
accretions[account postingct] = $0
|
||||
}
|
||||
|
||||
amount ~ /-/ {
|
||||
deductions[account postingct] = $0
|
||||
}
|
Loading…
Reference in New Issue
Block a user