Home > front end >  Right justify amounts in hledger journal text file
Right justify amounts in hledger journal text file

Time:12-12

I have a text file and I'm trying to right-align / justify the amounts (123.00 EUR) to a specified column number (say 53) by stretching the spaces before them appropriately

# 2018

; A comment



* Transactions

2018-01-01 @Payee | Internet
    expenses:communication:internet      123.00 EUR
    assets:cash:eur

2018-01-01 @Landlady | Rent
    expenses:housing:rent      321.00 EUR
    expenses:fees                2.50 EUR  ; Bank fee
    assets:bank:eur

The output should be

# 2018

; A comment



* Transactions

2018-01-01 @Payee | Internet
    expenses:communication:internet       123.00 EUR
    assets:cash:eur

2018-01-01 @Landlord | Rent
    expenses:housing:rent                 321.00 EUR
    expenses:fees                           2.50 EUR  ; Bank fee
    assets:bank:eur

It could probably be done with awk or printf or something but I can't figure it out.

More about the issue in the narrow sense as applied to hledger at Add option to print with normalized output width · Issue #1045 · simonmichael/hledger

CodePudding user response:

Using jq:

jq --raw-input --raw-output --argjson alignToColumn 53 '
  "\\d \\.?\\d*\\s EUR" as $searchPattern |   # regular expression to search for in each line
  if test($searchPattern)                     # test if line contains "xxxxx.xx EUR"
  then match($searchPattern) as $match |      # match "xxxxx.xx EUR"
       sub($searchPattern;
           " " * ($alignToColumn - $match.offset - $match.length)     # add leading spaces to matched "xxxxx.xx EUR"
           $match.string)
  else .                                      # no match found in line
  end
' file.txt

Remark

If a line contains more then one "xxxxx.xx EUR", the first match is aligned (see extra line "other stuff" in the output below)

Output

# 2018

; A comment



* Transactions

2018-01-01 @Payee | Internet
    expenses:communication:internet        123.00 EUR
    assets:cash:eur

2018-01-01 @Landlady | Rent
    expenses:housing:rent                  321.00 EUR
    expenses:fees                            2.50 EUR  ; Bank fee
    other stuff                                 7 EUR, 12.34 EUR
    assets:bank:eur

CodePudding user response:

According to hledger's manual, the field separator seems to be two or more spaces.

You should be able to use it for picking up the lines that contain an account and an amount.

Here's an awk idea for re-indenting the whole file with a given number of space characters while right-aligning the amounts:

awk -F ' {2,}|^  ' -v OFS='    ' '
    FNR == NR {
        if ( $1 !~ /^;/ ) {
            if ( NF >= 2 && $2 !~ /^;/ ) {
                account_size[FNR] = length($2)
                if ( max_account_size < account_size[FNR] )
                    max_account_size = account_size[FNR]
                if ( NF >= 3 && $3 !~ /^;/ ) {
                    amount_size[FNR] = length($3)
                    if ( max_amount_size < amount_size[FNR] )
                        max_amount_size = amount_size[FNR]
                }
            }
        }
        next
    }
    FNR in account_size {
        $2 = (FNR in amount_size) ? sprintf("%-" max_account_size   (max_amount_size - amount_size[FNR]) "s", $2) : $2
    }
    1
' file.txt file.txt

note: it's a two-pass algorithm so you need to provide the file twice

# 2018

; A comment



* Transactions

2018-01-01 @Payee | Internet
    expenses:communication:internet    123.00 EUR
    assets:cash:eur

2018-01-01 @Landlady | Rent
    expenses:housing:rent              321.00 EUR
    expenses:fees                        2.50 EUR    ; Bank fee
    assets:bank:eur

remark: as you can see, the ; Bank fee comment was also indented with OFS

CodePudding user response:

Using GNU awk for the 3rd arg to match:

$ cat tst.awk
match($0,/^([[:space:]] [^[:space:]] )[[:space:]] ([0-9.]  [[:upper:]] )(.*)/,a) {
    $0 = sprintf("%-39s s%s", a[1], a[2], a[3])
}
{ print }

$ awk -f tst.awk file
# 2018

; A comment



* Transactions

2018-01-01 @Payee | Internet
    expenses:communication:internet        123.00 EUR
    assets:cash:eur

2018-01-01 @Landlady | Rent
    expenses:housing:rent                  321.00 EUR
    expenses:fees                            2.50 EUR  ; Bank fee
    assets:bank:eur
  • Related