Кажется, это работает:
#!/bin/bash
a=$(parallel --shellquote ::: "$@")
echo "$timeStamp" - Executing command: sudo /home/editini.sh $a
Протестировано с:
mylog '"I want a 2"x4"", said the 3 * captain"' to his friend
Он не будет заключен в кавычки, потому что (, как видно из теста )", может быть частью входных данных. Вместо этого используется \. Функция цитирования оболочки в GNU Parallel тщательно тестируется, поэтому я буду удивлен, если вы сможете дать ей входные данные, которые будут указаны неправильно.
Расширение идеи @RudiC:
awk -v RS='"' -v ORS= '{if(NR % 2){gsub(",","|"); print} else print RS $0 RS}' file
| "Hi, I am Tom"||"16"
"I3"| "Hi, I am Jerry"|"Mouse"|"17"
Это должно работать, когда "
цитируется путем удвоения, как в"""Hi, I am Tom"", said the DOG"
(так, как это делается в стандартном CSV ), а не когда экранируется обратная косая черта -. За исключением чередующегося текста без кавычек и кавычек, это не зависит от формата файла; это не обязательно должен быть действительный CSV.
С GNU gawk(gawk
)это можно упростить до
gawk -v RS='"' -v ORS= 'NR % 2 {gsub(",","|")} {print $0 RT}' file
То же самое сperl
:
perl -pe 'BEGIN{$/=q/"/} s/,/|/ if $. % 2' file
Если исправить пробелы вокруг запятых, как прокомментировал Эд, то
$ cat text.csv
,"Hi, I am Tom",,"16"
"I3","Hi, I am Jerry","Mouse","17"
$ csvformat -D '|' text.csv
|Hi, I am Tom||16
I3|Hi, I am Jerry|Mouse|17
csvformat
является частью csvkit :https://csvkit.readthedocs.io/en/1.0.2/scripts/csvformat.html
другие языки, которые вы, возможно, уже установили, поставляются с модулями CSV, такими как ruby :
$ ruby -rcsv -e 'CSV.foreach(ARGV.shift) {|row| puts CSV.generate_line(row, col_sep: "|")}' text.csv
|Hi, I am Tom||16
I3|Hi, I am Jerry|Mouse|17
С perl
, предполагая, что части в кавычках не содержат новых строк или экранированных кавычек:
perl -pe 's{(".*?")|,}{$1//"|"}ge' < your-file
Мы можем подойти к PBM упрощенно. способ построения с нуля регулярных выражений того, как выглядят поля:
Q=\" # the quote char
NQ="[^${Q}]" # a non-quote char
nqF="[^${Q},]*" # a non quoted field
qF="${Q}${NQ}*${Q}" # a quoted fieldwith no nested quotes
qFwq= "\(\(${qF}\)\{2\}\)*" # a quoted field with nested quotes
Позикс-сед:
$ sed -e "
H;s/.*//;x; # to place a marker at the beginning of pattern space
:a
s/\(\n\)\(${qFwq}\),/\2|\1/
s/\(\n\)\(${qF}\),/\2|\1/
s/\(\n\)\(${nqF}\),/\2|\1/
ta
s/\n//
" file.csv
Использование Perl:
$ perl -F\" -lane 'local $|;
$|-- or tr/,/|/ for @F;
print join q["], @F;
' file.csv
Предполагается, что записи csv не переходят на следующую строку.
Еще один способ справиться с этим :используя Perl, мы читаем в записи (новую строку, разделенную )и разделяем ее запятой.
Не просто запятая, а "особая" запятая, когда мы стоим и видим четное количество двойных кавычек до конца записи.
Затем установите разделитель элементов массива в вертикальной черте "|":
$ perl \
-F',(?=(?:(?:[^"]*"){2})*[^"]*$)' \
-pale '$"=q[|]; $_ = "@F"' file.csv
Это распространенная проблема с CSV, см. что такое -самый -самый -надежный -способ -для -эффективного -разбора -csv -с использованием -авк .
Только для ввода, такого как вы показали нам, и использования GNU awk для FPAT после избавления от пробелов вокруг вашего поля -разделительные запятые и установки RS на \r\n
, поскольку ваш входной файл имеет окончания строк DOS:
$ cat -v file
,"Hi, I am Tom",,"16"^M
"I3","Hi, I am Jerry","Mouse","17"^M
$ awk -v RS='\r\n' -v FPAT='[^,]*|"[^"]+"' -v OFS='|' '{NF; $1=$1} 1' file
|"Hi, I am Tom"||"16"
"I3"|"Hi, I am Jerry"|"Mouse"|"17"
NF;
предназначен для обхода текущей ошибки в gawk 5.0.1:https://lists.gnu.org/archive/html/bug-gawk/2019-11/msg00003.html
Конечно, теперь вы должны спросить себя -, что мне делать, если поле в кавычках содержит |
s, экранированные двойные кавычки(""
или\"
)или символы новой строки?
Один из подходов состоит в том, чтобы заменить запятые в двойных кавычках на неиспользуемые в тексте символы, заменить все остальные запятые на целевые символы, а затем заменить токены обратно на запятые:
$ awk -F'"' '
{for (i=2; i<=NF; i+=2) gsub (/,/, "\001", $i)
gsub (/,/, "|")
gsub (/\001/, ",")
}
1
' OFS='"' file
| "Hi, I am Tom"||"16"
"I3"| "Hi, I am Jerry"|"Mouse"|"17"
Кажется, вы также удалили пробелы в своем образце вывода?