Предположим, что фрагмент csv отформатирован неправильно, используя точку с запятой в качестве признака конца поля:
abc;d" "e"f;"ijk"
В соответствии с RFC4180 кавычка внутри поля должна быть представлена двумя кавычками:
abc;d"" ""e""f;"ijk"
Я пытался добиться этого с помощью sed
скрипт, который соответствует любому dquote, не предшествующему или не сопровождаемому терминатором поля (здесь ;
):
echo 'abc;d" "e"f;"ijk"' | sed -e 's/\([^;]\)"\([^;]\)/\1""\2/g'
Результат почти хороший:
abc;d"" "e""f;"ijk"
кроме двойной кавычки перед e
не совпадает и, следовательно, не дублируется.
Может ли кто-нибудь объяснить мне, почему это не работает, так как до и после e
точки с запятой нет.
Ваша вторая цитата не соответствует, потому что совпадение будет space quote e
, а space
уже потребляется предыдущим d quote space
.
Это учебный пример для поисковое соответствие, который соответствует, но не потребляет. К сожалению, поисковое сопоставление не реализовано в sed
. Если бы мне пришлось использовать sed
для этого я бы сначала заменил действительные кавычки на какой-то не встречающийся символ, затем удвоил все оставшиеся кавычки, а затем вернул действительные кавычки.
У Perl есть поиск по кругу, что (немного) проще для глаз:
$ echo 'abc;d" "e"f;"ijk"' | perl -pe 's/(?<!;)"(?![;\n])/""/'g
abc;d"" ""e""f;"ijk"
Перевод: цитата, которой не предшествует регулярное выражение ;
, за которым не следует регулярное выражение [;\n]
.
\ N присутствует, потому что perl считает его частью строки и, следовательно, будет соответствовать последней кавычке, если мы не запретим это.