regexes in sed: correspondência de um caractere que não é precedido ou seguido por um outro caractere específico

1

Assumir um snippet csv formatado incorretamente usando ponto-e-vírgula como terminador de campo:

abc;d" "e"f;"ijk"

De acordo com a RFC4180 , uma nota dentro de um campo deve ser representada por dois dquotes:

abc;d"" ""e""f;"ijk"

Eu tentei fazer isso com um script sed que corresponde a qualquer dote não precedido ou seguido pelo terminador de campo (aqui ; ):

echo 'abc;d" "e"f;"ijk"' | sed -e 's/\([^;]\)"\([^;]\)/""/g'

O resultado é quase bom:

abc;d"" "e""f;"ijk"

exceto as aspas duplas antes que o e não seja correspondido e, portanto, não seja duplicado.

Alguém pode me explicar por que isso não funciona, já que antes e depois do e não há ponto e vírgula.

    
por Stefan Armbruster 06.08.2016 / 13:46

1 resposta

1

A sua segunda cotação não é correspondida porque a correspondência seria space quote e e a space já é consumida pela d quote space precedente.

Este é um exemplo de livros didáticos para correspondência de referência , que corresponde, mas não consome. Infelizmente, a correspondência de referência não está implementada em sed . Se eu tivesse que usar sed para isso, eu primeiro substituiria as aspas válidas por algum caractere não-ocorrente, depois dobraria todas as citações restantes e então colocaria as aspas válidas de volta.

Perl tem correspondência de pareamento, o que é (um pouco) mais fácil para os olhos:

$ echo 'abc;d" "e"f;"ijk"' | perl -pe 's/(?<!;)"(?![;\n])/""/'g
abc;d"" ""e""f;"ijk"

Tradução: uma cotação não precedida pela regex ; , não seguida pela regex [;\n] .

O \ n existe porque o perl considera parte da linha e, portanto, corresponde à última citação, a menos que seja proibida.

    
por 06.08.2016 / 16:41

Tags