URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9975
[ Назад ]

Исходное сообщение
"Редактирование CSV"

Отправлено salvani , 12-Фев-15 16:56 
Приветствую!

Имеется CSV файл, в котором поля разделены запятыми, но если в значении поля присутствует символ "запятая", то такое поле взято в кавычки. Примерно вот так:

data1,data2,"34,56"

Вопрос в том, возможно ли с помощью awk или еще как-то из командной строки убрать кавычки, но при этом не испортить значения в третьем поле? То есть, привести файл к такому виду:

data1;data2;34,56


Содержание

Сообщения в этом обсуждении
"Редактирование CSV"
Отправлено Pahanivo , 13-Фев-15 15:00 
> Приветствую!
> Имеется CSV файл, в котором поля разделены запятыми, но если в значении
> поля присутствует символ "запятая", то такое поле взято в кавычки. Примерно
> вот так:

это не "примерно вот так", это и есть самый обычный CSV формат - иначе как отделить запятую формата от запятой данных?

> Вопрос в том, возможно ли с помощью awk или еще как-то из
> командной строки убрать кавычки, но при этом не испортить значения в
> третьем поле? То есть, привести файл к такому виду:
> data1;data2;34,56

можно
_НО_ конкретно в вашем примере нужно еще как-то гарантировать что в данных отсутствует новоиспеченный разделить, иначе на выходе получится хрень
поэтому ответ "можно" рождает новый вопрос "зачем"?
как бы не особо понятно чем конкретно не устраивает исходный кошерный CSV?


"Редактирование CSV"
Отправлено salvani , 13-Фев-15 16:09 
> как бы не особо понятно чем конкретно не устраивает исходный кошерный CSV?

тем, что дальше этот файл попадает в обработчик, написанный на PHP и он ожидает именно такой формат входящего файла
тем не менее, спасибо за ответ


"Редактирование CSV"
Отправлено Pahanivo , 13-Фев-15 16:54 
классический костыль

"Редактирование CSV"
Отправлено Andrey Mitrofanov , 13-Фев-15 15:09 
> 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
$ _


"Редактирование CSV"
Отправлено salvani , 13-Фев-15 16:11 
>> 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
> $ _

Ух ты, я подозревал, что будет круто, но не то чтобы так. Работает как ураган! Спасибо!


"Редактирование CSV"
Отправлено Pahanivo , 13-Фев-15 17:01 
<<<'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

удачи ...


"Редактирование CSV"
Отправлено Аноним , 14-Фев-15 00:27 
> удачи ...

Да это фигня, скорми вот это:
<<<'data1,data.2,"34,56\",33"


"Редактирование CSV"
Отправлено Алексей , 13-Фев-15 15:53 
# cat << EOF > csv-converter
#!/usr/bin/python

import csv
import sys

file1 = 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


"Редактирование CSV"
Отправлено salvani , 13-Фев-15 16:16 
>[оверквотинг удален]
>     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 даже мне, не написавшему ещё на нем ни строки, все ясно и понятно.
(кроме того, куда подевались кавычки)


"Редактирование CSV"
Отправлено Алексей , 13-Фев-15 18:57 
Кавычки пропали "автоматически" потому что разделитель сменился.

"Редактирование CSV"
Отправлено михалыч , 14-Фев-15 17:00 
блин, опоздал я, но, всё равно, ударим перлом по бездорожью ))

#!/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


"Редактирование CSV"
Отправлено Аноним , 14-Фев-15 20:08 
> блин, опоздал я, но, всё равно, ударим перлом по бездорожью ))
> while ($str =~ m{([^,"]+)|"(.*)"}g) {

Ну дык те же грабли что и для решения на ____g____awk от Андрейки :-\
То есть для какого то _конкретного_ случая, ну пойдёт, да ... а вот в обшем случае - грабли!
Есть же в цпане великолепный модуль csv - чего не заюзать?


"Редактирование CSV"
Отправлено михалыч , 15-Фев-15 19:29 
да есть конечно, но может у ТС чисто конкретно такая задача и ни грамма больше
да и модуль ставить надо, а иногда такой возможности нет

хотя он небольшой конечно и других модулей за собой не тянет

ну что ж, извольте ))

чисто на входную строку

#!/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'ом он владеет виртуозно, мастер меча

говорят, что талант не пропьешь и в землю не закопаешь
я с последним согласен, а насчет первого не уверен ))
но это уже оффтоп


"Редактирование CSV"
Отправлено Pahanivo , 15-Фев-15 22:25 
это просто какой-то новомодный тренда ...
один разбрасывает грабли по полю и радостный бегает по ним получая по лбу. сломав переносицу приходит сюда и спрашивает что не так. на что получает совет разложить грабли по феньшую и бегать задом наперед. радостный убегает набивать себе шишки на затылок.
мораль: дали бы ему лучше вилы - он бы либо сразу напоролся, либо бы хоть чем то пользоваться научился.

"Редактирование CSV"
Отправлено михалыч , 16-Фев-15 06:09 
> это просто какой-то новомодный тренда ...
> один разбрасывает грабли по полю и радостный бегает по ним получая по
> лбу. сломав переносицу приходит сюда и спрашивает что не так. на
> что получает совет разложить грабли по феньшую и бегать задом наперед.
> радостный убегает набивать себе шишки на затылок.
> мораль: дали бы ему лучше вилы - он бы либо сразу напоролся,
> либо бы хоть чем то пользоваться научился.

да ладно!!

ты что так кипятишься и в бутылку лезешь!?
а давай ему дадим всё и сразу - и грабли, и вилы, и ..

пусть пользуется на здоровье! нам то что с того? да нам не жаль!


"Редактирование CSV"
Отправлено Andrey Mitrofanov , 16-Фев-15 10:05 
> да есть конечно, но может у ТС чисто конкретно такая задача и ни грамма больше
> хотя он небольшой конечно и других модулей за собой не тянет
> не согласен, что у Андрейки, как говоришь, грабли

Постановка задачи "сделайте мне 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


"Редактирование CSV"
Отправлено михалыч , 16-Фев-15 10:24 
> Постановка задачи "сделайте мне CVS" сама по себе грабля.

ну.. может быть, может быть, вам оно виднее ))

> Аноним очень правильно поймал меня на баши^Wгавкизме. Спасибо ему за науку.

ух он какой! поймал таки! ловец жемчуга ))
ну.. за науку и крутых анонимов!

а если серьёзно, то у вас парни есть чему многому поучиться


"Редактирование CSV"
Отправлено Аноним , 17-Фев-15 01:15 
> Аноним очень правильно поймал меня на баши^Wгавкизме. Спасибо ему за науку.

... аноним слегка упал под стол ... выходит жив ещё дух старого опеннета?!
Зря я выходит в стёртом посте, одно староеврейское словечко ввернул? Andrey Mitrofanov - я думал ты специально. Был балбес, извини.

PS: Неее - это мне снится, не бывает на нынешних форумах так :)))