太棒了;如何交换帐户并删除减号
该文件包含多个这样的交易
输入:
2018/01/08 * Aldi
; MD5Sum: a587a267588505265ae437c43c978886
; CSV: 2018-1-8,aldi,40.85
Expenses:Groceries
Expenses:Unknown USD -40.85
; :Groceries:
预期输出:
2018/01/08 * Aldi
; MD5Sum: a587a267588505265ae437c43c978886
; CSV: 2018-1-8,aldi,40.85
Expenses:Groceries USD 40.85
Expenses:Unknown
; :Groceries:
请注意,最右侧的金额已被否定,并且它附加到Expenses:Groceries
而不是附加到Expenses:Unknown
。
答案1
使用 Perl 最简单的方法是一次读取所有数据,将其分成几节(大概以行首的 4 位数字开头),然后分别对每个节进行操作。由于问题中未完全指定数据,因此对数据进行了假设。
#!/usr/bin/perl
use strict;
my $data = join("", <>);
my @stanzas = split(/^(?=\d{4})/m, $data);
foreach my $st (@stanzas){
if($st =~ m/Expenses:(?!Unknown)\S+\s*$/m){
if($st =~ m/Expenses:Unknown\s+(USD\s+-[0-9.]+)/){
my $amount = $1;
$amount =~ s/-//;
$st =~ s/Expenses:(?!Unknown)(\S+)(\s*)$/Expenses:$1 $amount/m;
$st =~ s/Expenses:Unknown(\s+USD\s+-[0-9.]+)/Expenses:Unknown/;
}
}
}
print join("", @stanzas);
这里,该split()
函数使用前瞻模式(?=)
将整个输入拆分为开头为 4 位数字的行。
对于每个节,如果它的 Expenses 后面不跟着 Unknown,后面跟着非空格,然后只有空格,并且 Unknown 后面跟着一个负数,则捕获该数字及其前面的 USD,并删除负号。
结果被替换到第一个匹配的行中,并具有一定的固定空间量,并从未知行中删除。单独执行此操作允许这两个字段在节中采用不同的顺序。
最后,将这些节连接起来并打印。
答案2
在段落模式下使用 Perl,我们将一次处理一个段落,并从未知字段中提取美元费用,并将其粘贴到其他费用行中:
$ perl -p00 -e '
my @A = /^\h+Expenses:Unknown(\h+USD\h+)-(\d+\.\d+)$/m;
s/^\h+Expenses:\K((Unknown)\h|\S+).*$/$2 ? $2 : "$1@A"/gem if @A;
' file