( tr, ';' | tr -d '"' ) < input.csv > output.csv
Я бы использовал Perl
perl -pe 'tr/,"/;/d' input.csv > output.csv
- но эта конкретная задача не выходит за рамки SED. Вы не можете объединить два выражения.
Чтобы иметь возможность импортировать некоторые данные в определенный инструмент, мне нужно преобразовать файл CSV из этого формата.
"data","data","data data","data","123"
в этот формат
data;data;data data;data;123
Столбцы никогда не содержат какой - либо "
, ;
или, ,
но могут быть пробелы. В настоящее время я использую следующее
sed -e 's/","/;/g' -e 's/"//g' input.csv > output.csv
Хотя это прекрасно работает, мне интересно, если это можно сделать более элегантно, то есть
Спасибо за ваш вклад!
( tr, ';' | tr -d '"' ) < input.csv > output.csv
Я бы использовал Perl
perl -pe 'tr/,"/;/d' input.csv > output.csv
- но эта конкретная задача не выходит за рамки SED. Вы не можете объединить два выражения.
Что вы предпочитаете (perl, sed, awk), зависит от вас; они все сделают работу. Так как вы попросили sed, а остальные опубликованы, вот и вы. Это более простая форма вашего регулярного выражения и работает с вашей строкой примера:
$ sed -e 's/"//g; s/,/;/g' infile.csv > outfile.csv
Обратите внимание, что вы можете объединить два выражения с точкой с запятой после каждой замены. Протестировано с GNU sed v4.1.5.
Вот ваши оригинальные выражения присоединились:
$ sed -e 's/","/;/g; s/"//g' infile.csv > outfile.csv
Я вполне уверен, что возможно объединить две замены. Не уверен, что это было бы не случайно, и я уверен, что результат будет гораздо менее читабельным, чем сценарий вверху. Если я что-то придумаю (или кто-то еще взвешивает в комментариях), я добавлю это сюда.
Поскольку вы имеете дело с записями, awk
имеет больше смысла. Тем не менее, это не очень хорошо в CSV, так как разделители полей несколько изменчивы. Но если вы уверены, что все поля заключены в двойные кавычки, это будет работать:
awk -F'","' 'BEGIN { gsub(/(^")|("$)/, ""); $1=$1; print }'
Это устанавливает в качестве разделителя поля ввода awk значение " ","
" (включая внутренний набор двойных кавычек). Это почти работает, за исключением того, что вам приходится иметь дело с ведущими и конечными двойными кавычками, которые удаляются с помощью gsub
функции. Эти $1=$1
силы это перекомпилировать запись с новым полем выходного сепаратора, который был определен как ;
в блоке BEGIN, . Затем print
распечатывает всю запись.
Это немного аккуратнее:
awk -F '(^")|(",")|("$)' 'BEGIN { $1=$1; print }'
Он устанавливает в качестве разделителя поля ввода регулярное выражение, которое включает в себя двойные кавычки в начале и конце записи, но также заставляет его печатать пустое поле начала и конца поля. Вы можете легко избавиться от конечного поля:
awk -F '(^")|(",")|("$)' 'BEGIN { NF=NF-1; $1=$1; print }'
NF
число полей, и уменьшение его на единицу отрывает от последнего поля. Но я не могу придумать, как отрубить первое поле.
Если вы знаете, что у ввода всегда есть пять полей, вы можете сделать это:
awk -F '(^")|(",")|("$)' 'BEGIN { print $2,$3,$4,$5,$6 }'
Обратите внимание, что это избавляет от $1=$1
конструкции, которая нам нужна, только если мы печатаем (подразумевается) $ 0.
Все это говорит о том, что я, вероятно, в конечном итоге использовал Perl и один из многих доступных модулей CSV на CPAN .