нужен сценарий оболочки, чтобы изменить разделитель запятой на разделитель трубы - PullRequest
2 голосов
/ 04 декабря 2010

Мой ввод выглядит как "$130.00","$2,200.00","$1,230.63" и т. Д. Мой вопрос: как мне изменить запятую на |разделитель без избавления от запятой при фактическом вводе.Просто чтобы уточнить этот вход в CSV-файл с 40 столбцами и 9500 строк.Я хочу, чтобы мой вывод выглядел как

"$130.00"|"$2,200.00"|"$1,230.63"

Ответы [ 4 ]

1 голос
/ 04 декабря 2010

Чтобы сделать это надежно, вы должны использовать состояния, чтобы отслеживать, находитесь ли вы внутри строки или нет.Следующий скрипт на Perl должен работать:

#!/usr/bin/perl -w
use strict;
use warnings;

my $state_outside_string = 0;
my $state_inside_string  = 1;

my $state = $state_outside_string;

while (my $line = <>) {
    my @chars = split(//,$line);
    foreach my $char (@chars) {
        if ($char eq '"') {
            if ($state == $state_outside_string) {
                $state = $state_inside_string;
            } else {
                $state = $state_outside_string;
            }
        } elsif ($char eq ',') {
            if ($state == $state_outside_string) {
                print '|';
                next;
            }
        }
        print $char;
    }
}
1 голос
/ 04 декабря 2010

Имеет ли значение 'shell запускает скрипт Perl'?

Если так, я бы посмотрел на модуль Perl Text :: CSV . У вас будет два дескриптора CSV: один для чтения файла с атрибутом sep_char, установленным как запятая (стандарт, по умолчанию), а другой для записи файла с атрибутом sep_char, установленным как канал.

Рабочий скрипт

#!/usr/bin/env perl

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

die "Usage: $0 in_file out_file\n" unless scalar @ARGV == 2;
my $in  = Text::CSV->new({ binary => 1, blank_is_undef => 1 })
    or die "Horribly";
my $out = Text::CSV->new({ binary => 1, sep_char => '|',
                           always_quote => 1, eol => "\n" })
    or die "Horribly";
open my $fh_in,  '<', $ARGV[0]
    or die "Failed to open $ARGV[0] for reading ($!)";
open my $fh_out, '>', $ARGV[1]
    or die "Failed to open $ARGV[1] for writing ($!)";

while (my $fields  = $in->getline($fh_in))
{
    $out->print($fh_out, $fields);
}

close $fh_in  or die "Failed to close input ($!)";
close $fh_out or die "Failed to close output ($!)";

Пример ввода

"$130.00","$2,200.00","$1,230.63"
"EUR1.300,00",,
"GBP1,300.00","$2,200.00",

Пример вывода

"$130.00"|"$2,200.00"|"$1,230.63"
"EUR1.300,00"||
"GBP1,300.00"|"$2,200.00"|
1 голос
/ 04 декабря 2010

Если в вашем файле нет других запятых, вы можете использовать:

sed "s/,/|/g" filename > outputfilename

Если запятые находятся только между "" с, то:

sed 's/","/"|"/g' filename > outputfilename

Работаеткак это:

sh-3.1$ echo '"123,456","123,454"' |sed 's/","/"|"/g'
"123,456"|"123,454"

Если у вас все еще есть выражение в кавычках, например ",", и вы не хотите его менять, то, я думаю, это становится немного сложнее:)


Другое решение с Python, использующее выделенный модуль, вероятно, лучшее с точки зрения безопасности и необходимого кода:

import csv
inFilename = 'input.csv'
outFilename = 'output.csv'

r = csv.reader(open(inFilename))
w = csv.writer(open(outFilename,'w'), delimiter='|', quotechar='"', quoting=csv.QUOTE_NONNUMERIC)
w.writerows(list(r))

Безопасно и просто.Вы можете легко настроить это для других форматов, параметры довольно просты.

0 голосов
/ 18 июля 2012

Библиотека Ruby CSV была заменена на FasterCSV в 1.9;в более ранних версиях вы можете использовать камень fastercsv.

#!/usr/bin/env ruby

require "csv"

output = CSV.read("test.csv").map do |row|
  row.to_csv(:col_sep => "|")
end
puts output
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...