Regex Perl正则表达式查找和替换

Regex Perl正则表达式查找和替换,regex,perl,replace,substitution,Regex,Perl,Replace,Substitution,我是perl新手,我正在尝试找出一种查找和替换方法。我有一个很大的csv文件(实际上是分号分隔的)。文件中的一些数字(整数和小数)在数字后有一个负号。我需要把负号移到数字前面 例如:改变 ABC;10.00-;XYZ 到 我不知道如何在perl中实现这一点。有人能帮忙吗 问候,, Anand通常,replace命令是s/old/new/flags: s/( # start a capture group \d+ # first part of the n

我是perl新手,我正在尝试找出一种查找和替换方法。我有一个很大的csv文件(实际上是分号分隔的)。文件中的一些数字(整数和小数)在数字后有一个负号。我需要把负号移到数字前面

例如:改变

ABC;10.00-;XYZ

我不知道如何在perl中实现这一点。有人能帮忙吗

问候,,
Anand

通常,replace命令是
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-

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

通常,替换命令是
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-

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

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

while( my $line = <STDIN> )
{
    chop( $line );
    my @rec = split( ';', $line );
    map( s/^(\d*\.?\d+)\-$/-$1/, @rec );
    print join(';',@rec) . "\n";
}
while(我的$line=)
{
印章(行);
my@rec=split(“;”,$line);
地图(s/^(\d*\.?\d+)\-$/-$1/,@rec);
打印联接(“;”,@rec)。“\n”;
}

如果您确实需要担心转义和引用,那么使用而不是
拆分
,和
加入
操作

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

while( my $line = <STDIN> )
{
    chop( $line );
    my @rec = split( ';', $line );
    map( s/^(\d*\.?\d+)\-$/-$1/, @rec );
    print join(';',@rec) . "\n";
}
while(我的$line=)
{
印章(行);
my@rec=split(“;”,$line);
地图(s/^(\d*\.?\d+)\-$/-$1/,@rec);
打印联接(“;”,@rec)。“\n”;
}

如果您确实需要担心转义和引用,那么请使用而不是
拆分
,和
加入
操作

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

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

如果您注意到输出文件中出现不需要的更改,可以尝试取消注释
keep\u meta\u 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);
    }
}
使用严格;
使用警告;
使用自动模具;
使用Text::CSV;
my$out_ext=“.new”;
my$csv=Text::csv->new({
sep_char=>“;”,
#保持_meta_info=>1,
二进制=>1,
下线=>$/,
})或“死”。Text::CSV->error_diag();
对于我的$arg(@ARGV){
打开我的$input,,$arg.$out\u ext;
while(my$row=$csv->getline($input)){
对于(@$行){
s/([0-9\.]+)\-$/-$1/;
}
$csv->打印($output,$row);
}
}

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

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

如果您注意到输出文件中出现不需要的更改,可以尝试取消注释
keep\u meta\u 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);
    }
}
使用严格;
使用警告;
使用自动模具;
使用Text::CSV;
my$out_ext=“.new”;
my$csv=Text::csv->new({
sep_char=>“;”,
#保持_meta_info=>1,
二进制=>1,
下线=>$/,
})或“死”。Text::CSV->error_diag();
对于我的$arg(@ARGV){
打开我的$input,,$arg.$out\u ext;
while(my$row=$csv->getline($input)){
对于(@$行){
s/([0-9\.]+)\-$/-$1/;
}
$csv->打印($output,$row);
}
}

chop
应该是
chomp
。您可能希望在csv文件上使用
split
时要小心,因为这可能会导致对文件进行不必要的更改。From:
默认情况下,保留空的前导字段,删除空的尾随字段。
chop
可能应该是
chomp
。您可能希望在csv文件上使用
split
时要小心,因为这可能会导致对文件进行不必要的更改。From:
默认情况下,保留空的前导字段,删除空的尾随字段。
这不会弄乱日期吗?例如,
2011-01-01
将变成
-2011-0101
。是的,这是很有可能的。这就是为什么我说我总是先尝试真实数据的模式,看看我可能错过了什么。使用简单的正则表达式替换进行多次迭代通常比使用更通用的解决方案更容易。除非它是一个大文件,如OP所说,在这种情况下,您需要相当小心。你是对的,我们不能像OP自己那样调整代码。例如,在开始和结束处添加带分号的前瞻可能是谨慎的。是的,这是个好主意。“大”文件实际上并不意味着“复杂”。可能的情况是,该文件是某个度量值或任何东西的转储,格式非常简单,只有大量数据。但我想我们彼此都了解,剩下的就在海报上了。这不会弄乱日期吗?例如,
2011-01-01
将变成
-2011-0101
。是的,这是很有可能的。这就是为什么我说我总是先尝试真实数据的模式,看看我可能错过了什么。使用简单的正则表达式替换进行多次迭代通常比使用更通用的解决方案更容易