Приветствую!Имеется CSV файл, в котором поля разделены запятыми, но если в значении поля присутствует символ "запятая", то такое поле взято в кавычки. Примерно вот так:
data1,data2,"34,56"
Вопрос в том, возможно ли с помощью awk или еще как-то из командной строки убрать кавычки, но при этом не испортить значения в третьем поле? То есть, привести файл к такому виду:
data1;data2;34,56
> Приветствую!
> Имеется CSV файл, в котором поля разделены запятыми, но если в значении
> поля присутствует символ "запятая", то такое поле взято в кавычки. Примерно
> вот так:это не "примерно вот так", это и есть самый обычный CSV формат - иначе как отделить запятую формата от запятой данных?
> Вопрос в том, возможно ли с помощью awk или еще как-то из
> командной строки убрать кавычки, но при этом не испортить значения в
> третьем поле? То есть, привести файл к такому виду:
> data1;data2;34,56можно
_НО_ конкретно в вашем примере нужно еще как-то гарантировать что в данных отсутствует новоиспеченный разделить, иначе на выходе получится хрень
поэтому ответ "можно" рождает новый вопрос "зачем"?
как бы не особо понятно чем конкретно не устраивает исходный кошерный CSV?
> как бы не особо понятно чем конкретно не устраивает исходный кошерный CSV?тем, что дальше этот файл попадает в обработчик, написанный на PHP и он ожидает именно такой формат входящего файла
тем не менее, спасибо за ответ
классический костыль
> data1,data2,"34,56"
> data1;data2;34,56$ <<<'data1,data2,"34,56"' awk '{while(match($0,"([^\"]*)\"([^\"]+)\"(.*)",ss)){gsub(",",".",ss[2]);$0=ss[1] ss[2] ss[3]}print}'
data1,data2,34.56
$ _
>> data1,data2,"34,56"
>> data1;data2;34,56
> $ <<<'data1,data2,"34,56"' awk '{while(match($0,"([^\"]*)\"([^\"]+)\"(.*)",ss)){gsub(",",".",ss[2]);$0=ss[1]
> ss[2] ss[3]}print}'
> data1,data2,34.56
> $ _Ух ты, я подозревал, что будет круто, но не то чтобы так. Работает как ураган! Спасибо!
<<<'data1,data2,"34,56.00"' awk '{while(match($0,"([^\"]*)\"([^\"]+)\"(.*)",ss)){gsub(",",".",ss[2]);$0=ss[1] ss[2] ss[3]}print}'
data1,data2,34.56.00удачи ...
> удачи ...Да это фигня, скорми вот это:
<<<'data1,data.2,"34,56\",33"
# cat << EOF > csv-converter
#!/usr/bin/pythonimport csv
import sysfile1 = sys.argv[1]
file2 = sys.argv[2]with open(file1, 'rb') as f1, open(file2, 'wb') as f2:
reader = csv.reader(f1, delimiter=',')
writer = csv.writer(f2, delimiter=';')
for row in reader:
writer.writerow(row)
EOF# chmod +x csv-converter
# ./csv-converter /tmp/test.csv /tmp/test.out
# cat /tmp/test.csv
data1,data2,"34,56"
# cat /tmp/test.out
data1;data2;34,56
>[оверквотинг удален]
> writer = csv.writer(f2, delimiter=';')
> for row in reader:
> writer.writerow(row)
> EOF
> # chmod +x csv-converter
> # ./csv-converter /tmp/test.csv /tmp/test.out
> # cat /tmp/test.csv
> data1,data2,"34,56"
> # cat /tmp/test.out
> data1;data2;34,56Спасибо, Алексей. На python даже мне, не написавшему ещё на нем ни строки, все ясно и понятно.
(кроме того, куда подевались кавычки)
Кавычки пропали "автоматически" потому что разделитель сменился.
блин, опоздал я, но, всё равно, ударим перлом по бездорожью ))
#!/usr/bin/perl$str = shift;
@a;while ($str =~ m{([^,"]+)|"(.*)"}g) {
if ($1) {$s = $1}
else {$s = $2}
push @a, $s;
}print join ";", @a;
./test.pl 'data1,data2,"34,56"'
data1;data2;34,56
> блин, опоздал я, но, всё равно, ударим перлом по бездорожью ))
> while ($str =~ m{([^,"]+)|"(.*)"}g) {Ну дык те же грабли что и для решения на ____g____awk от Андрейки :-\
То есть для какого то _конкретного_ случая, ну пойдёт, да ... а вот в обшем случае - грабли!
Есть же в цпане великолепный модуль csv - чего не заюзать?
да есть конечно, но может у ТС чисто конкретно такая задача и ни грамма больше
да и модуль ставить надо, а иногда такой возможности нетхотя он небольшой конечно и других модулей за собой не тянет
ну что ж, извольте ))
чисто на входную строку
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;my $str = shift;
my $csv = Text::CSV->new({allow_loose_quotes=>1});$csv->parse($str);
my @a = $csv->fields();
print join ";", @a;проверяем
./test.pl '`data1,data.2,"34,56\",33"'
`data1;data.2;34,56\;33"чисто на файл /tmp/file
data1,data2,"34,56"
data1,data2,34.56
'data1,data.2,"34,56\",33"#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;my @b;
my $file = "/tmp/file";
open my $fh, "<", $file or die "$file: $!";my $csv = Text::CSV->new({allow_loose_quotes=>1});
while (my $row = $csv->getline($fh)) {
my @a = join ";", @$row;
push @b, "@a\n";
}
close $fh;print @b;
результат
data1;data2;34,56
data1;data2;34.56
'data1;data.2;34,56\;33"не согласен, что у Андрейки, как говоришь, грабли
awk'ом, sed'ом, grep'ом он владеет виртуозно, мастер мечаговорят, что талант не пропьешь и в землю не закопаешь
я с последним согласен, а насчет первого не уверен ))
но это уже оффтоп
это просто какой-то новомодный тренда ...
один разбрасывает грабли по полю и радостный бегает по ним получая по лбу. сломав переносицу приходит сюда и спрашивает что не так. на что получает совет разложить грабли по феньшую и бегать задом наперед. радостный убегает набивать себе шишки на затылок.
мораль: дали бы ему лучше вилы - он бы либо сразу напоролся, либо бы хоть чем то пользоваться научился.
> это просто какой-то новомодный тренда ...
> один разбрасывает грабли по полю и радостный бегает по ним получая по
> лбу. сломав переносицу приходит сюда и спрашивает что не так. на
> что получает совет разложить грабли по феньшую и бегать задом наперед.
> радостный убегает набивать себе шишки на затылок.
> мораль: дали бы ему лучше вилы - он бы либо сразу напоролся,
> либо бы хоть чем то пользоваться научился.да ладно!!
ты что так кипятишься и в бутылку лезешь!?
а давай ему дадим всё и сразу - и грабли, и вилы, и ..пусть пользуется на здоровье! нам то что с того? да нам не жаль!
> да есть конечно, но может у ТС чисто конкретно такая задача и ни грамма больше
> хотя он небольшой конечно и других модулей за собой не тянет
> не согласен, что у Андрейки, как говоришь, граблиПостановка задачи "сделайте мне CVS" сама по себе грабля. См. у ESR-а в TAOUP в главе про форматы/протоколы. Кто ж я такой, чтоб усложнять _себе :/ задачу или требовать однозначных и полных постановок. Я и так срезал и поменял постановку, вместо заказанных раззделителя(,)->; сделал внутри-полей(,)->. .
> awk'ом, sed'ом, grep'ом он владеет виртуозно, мастер меча
Аноним очень правильно поймал меня на баши^Wгавкизме. Спасибо ему за науку.
Третий аргумент match(), так мною любимый, да, является расширением GNU и не работает, например, в mawk и даже в 'gawk -с' (и этот нехороший bait-n-lock не включает тот -с при запуске ч-з симлинк awk -> gawk, ату его, ребята).
awk: cmd. line:1: ^ match: third argument is a gawk extension
> Постановка задачи "сделайте мне CVS" сама по себе грабля.ну.. может быть, может быть, вам оно виднее ))
> Аноним очень правильно поймал меня на баши^Wгавкизме. Спасибо ему за науку.
ух он какой! поймал таки! ловец жемчуга ))
ну.. за науку и крутых анонимов!а если серьёзно, то у вас парни есть чему многому поучиться
> Аноним очень правильно поймал меня на баши^Wгавкизме. Спасибо ему за науку.... аноним слегка упал под стол ... выходит жив ещё дух старого опеннета?!
Зря я выходит в стёртом посте, одно староеврейское словечко ввернул? Andrey Mitrofanov - я думал ты специально. Был балбес, извини.PS: Неее - это мне снится, не бывает на нынешних форумах так :)))