Назад | Перейти на главную страницу

регулярные выражения в sed: сопоставление символа, которому не предшествует или не следует конкретный другой символ

Предположим, что фрагмент 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 считает его частью строки и, следовательно, будет соответствовать последней кавычке, если мы не запретим это.