对分类帐日记账文本文件中的金额进行右对齐



我有一个文本文件,我正试图右对齐/调整数量(123.00 EUR)到指定的列号(说53)通过适当地拉伸它们之前的空格

# 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

输出应该是

# 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

可能是awkprintf之类的,但我想不出来。

关于狭义上的问题的更多信息,请参见添加选项以标准化输出宽度打印·issue #1045·simmonmichael/hledger

使用GNU awk来匹配第三个参数:

$ cat tst.awk
match($0,/^([[:space:]]+[^[:space:]]+)[[:space:]]+([0-9.]+ [[:upper:]]+)(.*)/,a) {
$0 = sprintf("%-39s %13s%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

我使用%-39s %13s而不是上面的%-40s%13s,以确保您在两个字段之间获得空格,即使第一个字段最终超过40个字符。

使用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

不使用"if-then-else":

更紧凑的版本
jq --raw-input --raw-output --argjson alignToColumn 53 '
"\d+\.?\d*\s+EUR" as $searchPattern |
( match($searchPattern) as $m
| .[:$m.offset] + ($alignToColumn - $m.offset - $m.length) * " " + .[$m.offset:]
) // .
' file.txt

评论

如果一行包含多个"xxxxx。xx EUR",第一个匹配是对齐的(见额外的一行"其他东西")在下面的输出中)

输出

# 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

根据hledger手册,字段分隔符为两个或多个空格.

同样,account的行至少有2个(未注释)字段,amount的行有3个(未注释)字段。

您可以使用这个事实来区分带有amount的行与其他行。

这是一个awk的想法,使用给定数量的空格重新缩进整个文件,同时右对齐数量;这和你问的有点不同因为你不需要指定要移动金额的列,它会根据最大帐户字符串对它们进行对齐:

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

<一口>注意:这是一个两遍算法所以你需要提供两次文件

# 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

<一口>备注:如您所见,; Bank fee注释被认为是一个字段,因此它被OFS

缩进

最新更新