我需要一个shell脚本将逗号分隔符更改为管道分隔符

h22fl7wq  于 2023-03-24  发布在  Shell
关注(0)|答案(5)|浏览(139)

我的输入看起来像"$130.00","$2,200.00","$1,230.63"等等我的问题是如何将逗号分隔符更改为|分隔符而不去掉实际输入中的逗号。只是为了澄清这个输入是在一个40列9500行的csv文件中。我希望我的输出看起来像这样

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

v09wglhw1#

为了可靠地做到这一点,你必须使用状态来跟踪你是否在一个字符串中。下面的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;
    }
}
taor4pac

taor4pac2#

让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"|
aemubtdh

aemubtdh3#

如果文件中没有其他逗号,可以用途:

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

如果逗号仅在"" s之间,则:

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))

安全和简单。你可以很容易地为其他格式调整这个,参数相当简单。

dvtswwa3

dvtswwa34#

Ruby的CSV库在1.9中被替换为FasterCSV;在早期版本中,您可以使用fastercsv gem。

#!/usr/bin/env ruby

require "csv"

output = CSV.read("test.csv").map do |row|
  row.to_csv(:col_sep => "|")
end
puts output
arknldoa

arknldoa5#

我有同样的问题,我没有任何完美的解决方案,所以我尝试如下:

for file in `find $1 -name "*.csv"`
        do
            extension=`echo $file | awk -F . '{print $NF}'`
            fileName=`basename $file .csv`
            cat $file | awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "~", $i) } 1' > "$fileName.txt"
            cat "$fileName.txt" | sed 's/,/|/g' > pipedelimited.txt
            cat pipedelimited.txt | sed 's/~/,/g' > "$fileName.txt"
            rm -rf pipedelimited.txt
            echo "File Convert is complted for $file"
done

这将为传递给shell脚本的目录下的所有文件创建管道分隔的文件。这也处理了转义字符,该字符在一列中有额外的逗号。

相关问题