複数行で文字列を置き換える方法

複数行で文字列を置き換える方法

素晴らしいです。アカウントを交換してマイナス記号を削除する方法です。

ファイルには、次のような複数のトランザクションが含まれています。

入力する:

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つのフィールドをセクション内で異なる順序で配置できます。

最後に、セクションが接続されて印刷されます。

おすすめ記事