Регулярные выражения в sed: сопоставление символа, которому не предшествует или после которого не указан другой другой символ
Предположим, что неправильно отформатированный фрагмент csv использует точку с запятой в качестве ограничителя поля:
abc;d" "e"f;"ijk"
Согласно RFC4180, кавычка внутри поля должна быть представлена двумя кавычками:
abc;d"" ""e""f;"ijk"
Я пытался добиться этого с помощью sed
script that matches any dquote not preceeded or followed by the field terminator (here ;
):
echo 'abc;d" "e"f;"ijk"' | sed -e 's/\([^;]\)"\([^;]\)/\1""\2/g'
The result is almost good:
abc;d"" "e""f;"ijk"
except the double quote before the e
is not matched and therefore not duplicated.
Can anyone explain me why this doesn't work, since before and after the e
there's no semicolon.
1 ответ
Ваша вторая цитата не соответствует, потому что совпадение будет 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 считает его частью строки и поэтому будет соответствовать последней кавычке, если мы не запретим это.