У меня есть TSV с полями, которые выглядят так:
name location 1,2,3,4,5
Когда я использую sed 's/\w/,/g'
я получаю csv, где 1,2,3,4 и 5 считаются отдельными записями.
Я бы хотел, чтобы это было '1 2 3 4 5'
Я попытался преобразовать запятые в пробел перед запуском вышеуказанной команды, используя
sed 's/,/\w/g'
однако при преобразовании пробелов обратно в запятые он включает в себя одиночные пробелы, а также вкладки, так что же такое регулярное выражение только для одного символа пробела?
Желаемый результат:
name, location,1 2 3 4 5,
В моем текстовом редакторе (возвышенный текст) они выглядят как вкладки
разделители в значениях CSV обычно обрабатываются путем заключения значений в кавычки, например. name,location,"1,2,3,4,5"
. Считаете ли вы такое решение приемлемым?
Да, это было бы здорово
Как упоминалось в комментарии, CSV обычно имеет дело с появлением своего символа-разделителя в значениях, заключая значение в кавычки, поэтому я предлагаю вам просто справиться с этим, заключив каждое значение в кавычки:
sed -E 's/([^\t]*)(\t|$)/"\1",/g'
Вы можете попробуй здесь.
Это оставляет запятую в конце, как в вашем образце вывода, если вы хотите избежать этого, вы можете использовать следующее:
sed -E 's/\t+$//;s/^/"/;s/\t/","/g;s/$/"/'
Однако, если ваши исходные данные содержат "
, вам нужно будет избежать их, чего вы можете добиться, добавив следующую замену перед другими:
s/"/\\"/g
Как предполагает Эд Мортон, мы также можем удалить завершающие пустые поля:
s/\t+$//
В заключение я бы использовал следующее:
sed -E 's/"/\\"/g;s/\t+$//;s/^/"/;s/\t/","/g;s/$/"/'
который вы можете попробовать здесь.
@EdMorton запятая в конце была в образце вывода OP, и мой ответ упоминает об этом и предлагает альтернативу. Я исправил две другие проблемы, хотя.
Вау, я даже не заметил, что ОП тоже хотел заменить все свои запятые на пробелы в этом последнем поле! То, что у вас есть сейчас, лучше, но оно удалит любое пустое поле в конце строки.
Я только что проголосовал за это, а затем заметил, что полученный CSV сломал jquery-csv. После долгих поисков я обнаружил, что вам нужно избегать двойных кавычек с помощью еще одна двойная цитата! Таким образом, в результате получится команда sed -E 's/"/""/g;s/\t+$//;s/^/"/;s/\t/","/g;s/$/"/'
, которая хорошо подошла для моих целей.
Либо замените вкладки на ","
и заключите строки в двойные кавычки, либо замените запятые пробелами, а табуляции запятыми. В обоих случаях вы получите действительный CSV.
$ cat file
name location 1,2,3,4,5
$
$ sed 's/\t/","/g; s/^\|$/"/g' file
"name","location","1,2,3,4,5"
$
$ sed 's/,/ /g; s/\t/,/g' file
name,location,1 2 3 4 5
И в авке:
$ awk -v OFS = "," '{for(i=1;i<=NF;i++)if ($i~/,/)$i = "\"" $i "\"";$1=$1}1' file
name,location,"1,2,3,4,5"
Объяснение:
$ awk -v OFS = "," '{ # output delimiter to a comma *
for(i=1;i<=NF;i++) # loop all fields
if ($i~/,/) # if comma in field
$i = "\"" $i "\"" # surround with quotes **
$1=$1 # rebuild record
}1' file # output
* если в записи есть место, считайте разделителем полей ввода табуляцию с awk -F"\t"
.
** так же, если в полях с запятыми стоят кавычки, возможно, их стоит продублировать или экранировать.
В зависимости от ваших реальных требований:
$ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) $i = "\""$i"\""} 1' file
"name","location","1,2,3,4,5"
$ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) gsub(OFS," ",$i); $1=$1} 1' file
name,location,1 2 3 4 5
$ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) gsub(OFS," ",$i); $(NF+1) = ""} 1' file
name,location,1 2 3 4 5,
$ echo 'a"b' | awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) { gsub(/"/,"\"\"",$i); $i = "\""$i"\"" } } 1'
"a""b"
Вы уверены, что входной файл разделен табуляцией или это просто куча пробелов?