我有一个包含500.000+行的巨大csv文件。我想在" Price"列通过Ubuntu中的终端。我尝试使用awk(最佳解决方案?)但我不知道如何。 (我还需要将标题保留在新文件中)
以下是文件
的示例"Productno.";"Description";"Price";"Stock";"Brand"
"/5PL0006";"Drum Unit";"379,29";"10";"Kyocera"
"00096103";"Main pcb HUK, OP6w";"882,00";"0";"OKI"
"000J";"Drum, 7033/7040 200.000";"4306,00";"0";"Minolta"
我想例如,在价格上加125,输出为:
"Productno.";"Description";"Price";"Stock";"Brand"
"/5PL0006";"Drum Unit";"504,29";"10";"Kyocera"
"00096103";"Main pcb HUK, OP6w";"1007,00";"0";"OKI"
"000J";"Drum, 7033/7040 200.000";"4431,00";"0";"Minolta"
答案 0 :(得分:2)
$ awk 'BEGIN {FS=OFS="\";\""} NR>1 {$3 = sprintf("%.2f", $3+125)}1' p.txt
"Productno.";"Description";"Price";"Stock";"Brand"
"/5PL0006";"Drum Unit";"504,29";"10";"Kyocera"
"00096103";"Main pcb HUK, OP6w";"1007,00";"0";"OKI"
"000J";"Drum, 7033/7040 200.000";"4431,00";"0";"Minolta"
请注意,这需要一个环境变量LC_NUMERIC
的值,期望,
作为小数点分隔符(我将我的设置为LC_NUMERIC="de_DE"
,例如。)。
对于更多干燥,您可以使用-v
传递要添加的金额:
$ awk -v n=125 'BEGIN {FS=OFS="\";\""} NR>1 {$3 = sprintf("%.2f", $3+n)}1' p.txt
如果您不太关心格式化(即,如果"4431"
而不是"4431,00"
可以接受),则可以跳过sprintf
:
$ awk -v n=125 'BEGIN {FS=OFS="\";\""} NR>1 {$3+=n}1' p.txt
编辑:在FS
块中设置OFS
和BEGIN
,而不是通过-v
独立设置,如评论中所示(为了更好确保他们获得相同的价值,因为它们是相同的重要。)
答案 1 :(得分:0)
add-price
,以perl add-price input.csv 125
运行。
#!/usr/bin/perl
use warnings;
use strict;
use Text::CSV;
my ($file, $add) = @ARGV;
my $csv = 'Text::CSV'->new({ binary => 1,
sep_char => ';',
eol => "\n",
always_quote => 1,
}) or die 'Text::CSV'->error_diag;
open my $IN, '<', $file or die $!;
open my $OUT, '>', "$file.new" or die $!;
while (my $row = $csv->getline($IN)) {
if (1 != $csv->record_number) {
my $value = $row->[2];
$value =~ s/,/./;
$value = sprintf "%.2f", $value + $add;
$value =~ s/\./,/;
$row->[2] = $value;
}
$csv->print($OUT, $row);
}
close $OUT or die $!;
答案 2 :(得分:0)
你也可以使用php和这个很棒的库:https://github.com/parsecsv/parsecsv-for-php:
首先下载库,将其添加到新文件夹并将CSV文件的副本添加到该文件夹(确保使用副本,如果您执行此库的保存方法可以删除csv文件的数据不能正确使用它):
使用此库,您可以直接解析和修改值!
<?php
// !!! Make a copy of your csv file before executing this
// Require the Parse CSV library , that you can find there : https://github.com/parsecsv/parsecsv-for-php
require_once 'parsecsv.lib.php';
// Instanciate it
$csv = new parseCSV();
// Load your file
$csv->auto('data.csv');
// Get the number of data rows
$nb_data_rows=count($csv->data)-1;
// Iterate through each data row.
for ($i = 0; $i <= $nb_data_rows; $i++) {
// Define the new Price
$new_price=$csv->data[$i]["Price"]+125;
// Format the price in order to keep two decimals
$new_price=number_format($new_price, 2, '.', '');
// Modify the ith value of your csv data
$csv->data[$i]=array(
"Productno."=> $csv->data[$i]["Productno."],
"Description."=> $csv->data[$i]["Description"],
"price"=>$new_price,
"Stock"=> $csv->data[$i]["Stock"],
"Brand"=> $csv->data[$i]["Brand"] );
// save it !
$csv->save();
}
答案 3 :(得分:0)
如果您不担心&#39;;&#39;发生在前两个字段中,如果您不想依赖环境变量,请考虑:
awk -F';' -v add=125 '
function sum(s, d) { # global: q, add
gsub(q, "", s);
split(s,d,",");
return (add+d[1])","d[2];
}
BEGIN {OFS=FS; q="\""; }
NR>1 {$3 = q sum($3) q}
{print} '
这会保留双引号("
)。使用您的输入,上面的脚本生成:
"Productno.";"Description";"Price";"Stock";"Brand"
"/5PL0006";"Drum Unit";"504,29";"10";"Kyocera"
"00096103";"Main pcb HUK, OP6w";"1007,00";"0";"OKI"
"000J";"Drum, 7033/7040 200.000";"4431,00";"0";"Minolta"