Perl正则表达式找到并替换

时间:2011-08-01 06:56:01

标签: regex perl replace substitution

我是perl的新手,我正在试图找出并替换。我有一个大的csv文件(实际上是分号分隔)。文件中的某些数字(int和decimal)在数字后面有一个负号。我需要将负号移到数字前面。

E.g:改变

ABC;10.00-;XYZ

ABC;-10.00;XYZ

我不确定如何在perl中执行此操作。有人可以帮忙吗?

此致 阿南德

3 个答案:

答案 0 :(得分:2)

除非我非常确定我的数据和正则表达式,否则我不会涉及带有正则表达式的大型csv文件。在我看来,使用CSV模块是最安全的方式。

此脚本将输入文件作为参数,并使用.new扩展名编写更正的文件。

如果您发现输出文件发生了意外更改,可以尝试取消评论keep_meta_info行。

use strict;
use warnings;
use autodie;
use Text::CSV;

my $out_ext = ".new";
my $csv = Text::CSV->new( { 
        sep_char => ";",
        #   keep_meta_info => 1,
        binary => 1,
        eol => $/,
    } ) or die "" . Text::CSV->error_diag();

for my $arg (@ARGV) {
    open my $input, '<', $arg;
    open my $output, '>', $arg . $out_ext;
    while (my $row = $csv->getline($input)) {
        for (@$row) {
            s/([0-9\.]+)\-$/-$1/;
        }
        $csv->print($output, $row);
    }
}

答案 1 :(得分:1)

我假设您不必担心在分隔文件中引用或转义。我将从标准输入/输出读取,如果需要,则更改为适当的文件

while( my $line = <STDIN> )
{
    chop( $line );
    my @rec = split( ';', $line );
    map( s/^(\d*\.?\d+)\-$/-$1/, @rec );
    print join(';',@rec) . "\n";
}

如果您不必担心转义和引用,请使用Text::CSV_XS代替<STDIN>splitjoin oprerations

答案 2 :(得分:0)

通常,替换命令为s/old/new/flags

s/(           # start a capture group
    \d+       # first part of the number
    (\.\d+)?  # possibly a decimal dot and the fractional part
  )-          # end capture group, match the minus sign
 /-$1/gx      # move minus to the front

g标志表示“全局”(替换所有出现),x是“扩展易读性”(允许模式中的空格和注释)。您必须在数据上测试表达式以查看可能遗漏的角落情况,通常需要几次迭代才能获得正确的情况。样品:

$ echo "10.5-;10-;0-;a-" | perl -pe 's/(\d+(\.\d+)?)-/-$1/g'
-10.5;-10;-0;a-

另请参阅perldoc perlop(搜索“替换”以跳转到右侧部分)。