如何在多行中交换字符串

如何在多行中交换字符串

太棒了;如何交换帐户并删除减号

该文件包含多个这样的交易

输入:

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

相关内容