需要为一个有句子的文件创建正则表达式

时间:2016-12-06 06:15:57

标签: perl

L02    TIME DEPOSITS                             489,26,45,422.92                                                   
L18    DRAFTS ACCOUNT (IF CREDIT)                10,063.00           10,063.00                                                
L21    SBI BILLS ACCOUNT (CONTRA) A18                              37,51,432.00 
A12A   DEMAND LOANS                                               4,39,13,597.30                      

这些是我文件中的行我想要从每行(L或A)开始提取金额并存储到变量中。

这就是我写的

pattern =/[A-Z]\w+\s*([\d,.]*)\s*([\d,.])*/g
$first = $1;
$second= $2;  

1 个答案:

答案 0 :(得分:1)

你的正则表达式在中间寻找一串\w然后空格,因此它不能匹配多个单词。最后一个*应该在括号内,就像第一个(但见下文)。 [A-Z]匹配任何块资金,而您表示需要AL,因此请改用[AL]

my @amounts = $string =~ /^[AL]\w+ \s+ [A-Za-z ]* ([\d,.]*)/xg;

您不希望使用*量词重复该模式,以便考虑可变数量的事件。当需求变化时2变为3会怎样?四?相反,您可以捕获数组中的所有匹配并获得与之相同的数量。

/x允许我们在里面使用空格以便于阅读。

这是另一种更灵活的方法。

您需要一个包含任何数字的模式,,(逗号),.(句点) - 并且只能在字符串中使用。您只希望在以AL开头的行中使用此功能。

因此,请跳过不以AL开头的行,然后仅匹配所需的模式。

use warnings;
use strict;

my $filename = '...';
open my $fh, '<', $filename or die "Can't open $filename: $!";

while (<$fh>)
{
    next unless /^[AL]/;   # skip if the line doesn't start with A or Z

    my @amounts = $_ =~ /\b ([\d,.]+) \b/xg;

    print "@amounts\n" if @amounts;
}
close $fh;

在这里,您需要指定\b字边界。否则,02中的L02会匹配,例如。

如果没有匹配,则数组为空,因此我们测试,不打印空行。调整合适。

减少对正则表达式详细信息的依赖并使代码更加灵活的下一步是split按空格划分的行和逐个处理的行。然后调整就容易得多,可以吸收变化。

例如,这有助于评论中提到的数据更改 - 如果有日期会怎么样?上面的正则表达式将匹配数字部分,而第一个正则表达式将崩溃。

在每一行的字段上循环,我们可以跳过日期next if /\d{4}-\d{2}/;