Cortar una cadena por un caracter solo cuando no forme parte de una subcadena entrecomillada

Algunos usuarios del paquete pxR han avisado de un error de implementación. Según las especificaciones del formato de datos PC-Axis, las líneas de ese tipo de ficheros acaban en punto y coma (y no necesariamente en un salto de línea).

Así que era natural leer los ficheros íntegramente, concatenar sus líneas físicas y luego partirlas usando strsplit para obtener las líneas lógicas.

Sin embargo, ciertos ficheros contienen descripciones (entrecomilladas) que contienen puntos y comas. Y eso produce caos.

El problema planteado consiste entonces en partir una cadena por un determinado caracter (punto y coma en nuestro caso) solo cuando no forme parte de una subcadena entrecomillada. Lancé la pregunta en r-help-es y obtuve algunas respuestas desiguales. La más próxima a la respuesta que quería era la de Francisco Viciana que funcionaba… excepto cuando en la cadena había caracteres no ASCII (o multibyte) por alguna razón técnica que se me escapa.

Así que me manché las manos y he aquí la solución con la que vine a dar:

library(stringr)

a <- '1,2,"algo;todo"; 3,"¿cósa"; 4,2,3,7;'

punto.coma <- str_locate_all(a, ";")[[1]][,1]
comillas <- str_locate_all(a, '"')[[1]][,1]

cortes <- Filter(function(x) sum(comillas < x) %% 2 == 0, punto.coma)

inicios <- c(1, cortes + 1)
finales <- c(cortes - 1, str_length(a))

str_sub(a, inicios, finales)

El quid reside en la llamada a Filter, que selecciona solo aquellas posiciones en las que hay puntos y comas que no están precedidas por un número impar de comillas. El paquete stringr resulta instrumental: proporciona recursos para procesar cadenas de texto no disponibles de una manera tan limpia y escueta entre las básicas de R.