Perl regex найти и заменить - PullRequest
       4

Perl regex найти и заменить

0 голосов
/ 01 августа 2011

Я новичок в Perl и пытаюсь найти и заменить. У меня есть большой CSV-файл (на самом деле разделенные точкой с запятой). Некоторые числа (целые и десятичные) в файле имеют отрицательный символ после числа. Мне нужно переместить знак минус до числа.

Например: изменить

ABC;10.00-;XYZ

до

ABC;-10.00;XYZ

Я не уверен, как это сделать в Perl. Может кто-нибудь помочь, пожалуйста?

С уважением, Ананд

Ответы [ 3 ]

2 голосов
/ 01 августа 2011

Я бы не стал копаться в большом 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 голос
/ 01 августа 2011

Полагаю, вам не нужно беспокоиться о цитировании или экранировании в файле с разделителями. Я буду читать из стандартного ввода / вывода, изменить на соответствующие файлы, если req'd

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

Если вам нужно беспокоиться о экранировании и цитировании, тогда используйте Text :: CSV_XS вместо операций <STDIN>, split и join

0 голосов
/ 01 августа 2011

Обычно команда замены - 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 (поиск «замена», чтобы перейти к правой части).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...