Когда я работаю с CSV, нежелательные запятые (',') вводят мой CSV-файл в заблуждение, в результате чего возникает несоответствие.
Подробную информацию вы найдете ниже.
Мой пример CSV-файла:
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
Я хочу получить конечный результат:
1|"a,b"|4
1|"c,d"|4
1|"e,f"|4
1|"g,h"|4
1|"i,j"|4
После добавления кавычек я заменю «|» на «,», чтобы мой CSV-файл работал так, как я и ожидал.
Я использовал команду ниже, но она не дала ожидаемого результата.
sed -e 's/,/"&"/' file1.txt
решение1
Используя csvformat
изcsvkit
и предполагая, что конечным результатом должен быть CSV-файл с запятой в качестве разделителя (как описано в тексте вопроса):
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
Это переформатирует CSV-файл с |
-символов в качестве разделителя на запятую по умолчанию. При этом поля, которые нужно закавычить, будут правильно заключены в кавычки.
Это также правильно обрабатывает поля со встроенными символами новой строки:
$ cat file
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
2|"line 1,
line2"|5
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
2,"line 1,
line2",5
Если у вас есть документ в каком-либо структурированном формате, например CSV, JSON, XML, YAML, TOML и т. д., то нет причиннетиспользовать анализатор для данного формата документа, чтобы проанализировать этот документ.
решение2
Вы можете сделать:
awk -F'[|]' -v OFS=',' -v q='"' '{ for(i=1; i<=NF; i++) $i=q $i q }1' infile
с -F'[|]'
мы определили разделитель входных полей.
с -v OFS=','
мы определили разделитель выходных полей.
NF
определяет, сколько полей содержится в каждой строке/записи на основе FS (разделитель входных полей), поэтому мы перебираем количество полей и добавляем двойные кавычки для каждого из них и печатаем окончательное обновление в строке с1
идиома awkдля печати.
обратите внимание, что при использовании этой команды все поля заключаются в кавычки, что, очевидно, не является проблемой для корректного файла CSV.
решение3
С sed
:
$ sed 's/[^|]*,[^|]*/"&"/g; y/|/,/' ip.txt
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
s/[^|]*,[^|]*/"&"/g
добавьте двойные кавычки ко всем полям, содержащим,
y/|/,/
изменить все|
символы на,
С perl
:
perl -F'\|' -lane 'print join ",", map {/,/ ? qq("$_") : $_} @F'
Это используется |
как разделитель полей ввода. Затем map
будут добавлены двойные кавычки для всех полей, содержащих ,
. Наконец, join
используется для объединения полей с ,
символом.
решение4
Другой sed
путь:
sed 's;\([^|]*\)|\([^|]*\)|\(.*\)$;\1,"\2",\3;' data
Или, если вы sed
поддерживаете загрузку ERE
, например GNU sed
, вы можете избежать всех экранирующих заданий:
sed -E 's;([^|]+)\|([^|]+)\|(.+)$;\1,"\2",\3;' data
Вы можете воспользоваться тем фактом, что только средняя группа отделена на |
каждой границе, и сделать sed
еще короче:
sed 's;|\([^|]*\)|;,"\1",;' data
Конечно, и здесь, если ваша поддержка sed, -E
вы можете загрузить ERE
и избежать утомительной работы по выходу из игры.