Tengo el siguiente tipo de cuerda
var string = "'string, duppi, du', 23, lala"
Quiero dividir la cadena en una matriz en cada coma, pero solo las comas fuera de las comillas simples.
No puedo encontrar la expresión regular correcta para la división ...
string.split(/,/)
me darás
["'string", " duppi", " du'", " 23", " lala"]
pero el resultado debería ser:
["string, duppi, du", "23", "lala"]
¿Existe una solución para varios navegadores?
javascript
regex
split
Hans
fuente
fuente
Respuestas:
Descargo de responsabilidad
Actualización de 2014-12-01: la respuesta a continuación solo funciona para un formato muy específico de CSV. Como señaló correctamente DG en los comentarios , esta solución no se ajusta a la definición de CSV de RFC 4180 y tampoco se ajusta al formato de Microsoft Excel. Esta solución simplemente demuestra cómo se puede analizar una línea de entrada CSV (no estándar) que contiene una combinación de tipos de cadenas, donde las cadenas pueden contener comillas y comillas de escape.
Una solución CSV no estándar
Como señala correctamente austincheney , realmente necesita analizar la cadena de principio a fin si desea manejar adecuadamente las cadenas entre comillas que pueden contener caracteres de escape. Además, el OP no define claramente qué es realmente una "cadena CSV". Primero debemos definir qué constituye una cadena CSV válida y sus valores individuales.
Dado: Definición de "Cadena CSV"
A los efectos de esta discusión, una "cadena CSV" consta de cero o más valores, donde varios valores están separados por una coma. Cada valor puede constar de:
Reglas / Notas:
'that\'s cool'
.\'
en valores entre comillas simples.\"
en valores entre comillas dobles.Encontrar:
Una función de JavaScript que convierte una cadena CSV válida (como se define arriba) en una matriz de valores de cadena.
Solución:
Las expresiones regulares que utiliza esta solución son complejas. Y (en mi humilde opinión) todas las expresiones regulares no triviales deben presentarse en modo de espacio libre con muchos comentarios y sangría. Desafortunadamente, JavaScript no permite el modo de espacio libre. Por lo tanto, las expresiones regulares implementadas por esta solución se presentan primero en la sintaxis de expresiones regulares nativas (expresadas utilizando la práctica
r'''...'''
sintaxis de cadena de múltiples líneas sin procesar de Python ).Primero, aquí hay una expresión regular que valida que una cadena CVS cumple con los requisitos anteriores:
Expresión regular para validar una "cadena CSV":
Si una cadena coincide con la expresión regular anterior, entonces esa cadena es una cadena CSV válida (de acuerdo con las reglas indicadas anteriormente) y se puede analizar utilizando la siguiente expresión regular. La siguiente expresión regular se usa luego para hacer coincidir un valor de la cadena CSV. Se aplica repetidamente hasta que no se encuentran más coincidencias (y se han analizado todos los valores).
Expresión regular para analizar un valor de una cadena CSV válida:
Tenga en cuenta que hay un valor de caso especial con el que esta expresión regular no coincide: el último valor cuando ese valor está vacío. Este caso especial de "último valor vacío" es probado y manejado por la función de JavaScript que sigue.
Función de JavaScript para analizar la cadena CSV:
Ejemplo de entrada y salida:
En los siguientes ejemplos, se utilizan llaves para delimitar el
{result strings}
. (Esto es para ayudar a visualizar espacios iniciales / finales y cadenas de longitud cero).Notas adicionales:
Esta solución requiere que la cadena CSV sea "válida". Por ejemplo, los valores sin comillas pueden no contener barras invertidas ni comillas, por ejemplo, la siguiente cadena CSV no es válida:
Esto no es realmente una limitación porque cualquier subcadena puede representarse como un valor entre comillas simple o doble. Tenga en cuenta también que esta solución representa sólo una posible definición de "valores separados por comas".
Editar historial
fuente
"field one", "field two", "a ""final"" field containing two double quote marks"
no he probado la respuesta de Trevor Dixon en esta página, pero es una respuesta que aborda la definición RFC 4180 de CSV.Solución RFC 4180
Esto no resuelve la cadena en la pregunta ya que su formato no se ajusta a RFC 4180; la codificación aceptable es escapar de comillas dobles con comillas dobles. La siguiente solución funciona correctamente con archivos CSV d / l de hojas de cálculo de Google.
ACTUALIZACIÓN (3/2017)
Analizar una sola línea sería incorrecto. Según RFC 4180, los campos pueden contener CRLF, lo que hará que cualquier lector de línea rompa el archivo CSV. Aquí hay una versión actualizada que analiza la cadena CSV:
ANTIGUA RESPUESTA
(Solución de una sola línea)
Y para divertirse, así es como crea CSV a partir de la matriz:
fuente
Gramática PEG (.js) que maneja ejemplos de RFC 4180 en http://en.wikipedia.org/wiki/Comma-separated_values :
Pruebe en http://jsfiddle.net/knvzk/10 o https://pegjs.org/online .
Descargue el analizador generado en https://gist.github.com/3362830 .
fuente
Tuve un caso de uso muy específico en el que quería copiar celdas de Google Sheets en mi aplicación web. Las celdas pueden incluir comillas dobles y caracteres de nueva línea. Al usar copiar y pegar, las celdas se delimitan con caracteres de tabulación y las celdas con datos impares se citan dos veces. Probé esta solución principal, el artículo vinculado usando regexp y Jquery-CSV y CSVToArray. http://papaparse.com/ Es el único que funcionó fuera de la caja. Copiar y pegar es perfecto con Google Sheets con opciones predeterminadas de detección automática.
fuente
Me gustó la respuesta de FakeRainBrigand, sin embargo, contiene algunos problemas: no puede manejar espacios en blanco entre una cita y una coma, y no admite 2 comas consecutivas. Intenté editar su respuesta, pero mi edición fue rechazada por revisores que aparentemente no entendieron mi código. Aquí está mi versión del código de FakeRainBrigand. También hay un violín: http://jsfiddle.net/xTezm/46/
fuente
La gente parecía estar en contra de RegEx por esto. ¿Por qué?
Aquí está el código. También hice un violín .
fuente
Añadiendo uno más a la lista, porque encuentro que todo lo anterior no es lo suficientemente "KISS".
Este usa expresiones regulares para encontrar comas o líneas nuevas mientras se salta los elementos citados. Con suerte, esto es algo que los novatos pueden leer por sí mismos. La
splitFinder
expresión regular tiene tres cosas que hace (dividida por a|
):,
- encuentra comas\r?\n
- encuentra nuevas líneas (potencialmente con retorno de carro si el exportador fue amable)"(\\"|[^"])*?"
- omite cualquier cosa entre comillas, porque las comas y las nuevas líneas no importan allí. Si hay una cotización escapada\\"
en el artículo cotizado, se capturará antes de que se pueda encontrar una cotización final.fuente
Id, Name, Age 1, John Smith, 65 2, Jane Doe, 30
¿cómo puedo analizar en función de las columnas que especifico?[{Id: 1, Name: "John Smith", Age: 65}, {Id: 2, Name: "Jane Doe", Age: 30}]
Si puede hacer que su delimitador de comillas sea comillas dobles, entonces este es un duplicado del código JavaScript de ejemplo para analizar datos CSV .
Primero puede traducir todas las comillas simples a comillas dobles:
... o puede editar la expresión regular en esa pregunta para reconocer comillas simples en lugar de comillas dobles:
Sin embargo, esto asume cierto marcado que no está claro en su pregunta. Aclare cuáles pueden ser todas las diversas posibilidades de marcado, según mi comentario sobre su pregunta.
fuente
Mi respuesta asume que su entrada es un reflejo de código / contenido de fuentes web donde los caracteres de comillas simples y dobles son completamente intercambiables siempre que ocurran como un conjunto de coincidencias sin escape.
No puede usar expresiones regulares para esto. De hecho, debe escribir un micro analizador para analizar la cadena que desea dividir. Por el bien de esta respuesta, llamaré a las partes citadas de sus cadenas como subcadenas. Necesitas caminar específicamente a través de la cuerda. Considere el siguiente caso:
En este caso, no tiene ni idea de dónde comienza o termina una subcadena simplemente analizando la entrada para un patrón de caracteres. En su lugar, debe escribir lógica para tomar decisiones sobre si un carácter de comillas se utiliza como carácter de comillas, si no está entre comillas y si el carácter de comillas no sigue un escape.
No voy a escribir ese nivel de complejidad de código para usted, pero puede ver algo que escribí recientemente que tiene el patrón que necesita. Este código no tiene nada que ver con las comas, pero por lo demás es un micro-analizador lo suficientemente válido para que lo siga escribiendo su propio código. Mire la función asifix de la siguiente aplicación:
https://github.com/austincheney/Pretty-Diff/blob/master/fulljsmin.js
fuente
Para complementar esta respuesta
Si necesita analizar comillas escapadas con otra cita, ejemplo:
Puedes usar
fuente
"jjj "" kkk""","123"
Mientras lee el archivo CSV en una cadena, contiene valores nulos entre las cadenas, así que inténtelo con \ 0 línea por línea. Esto funciona para mi.
fuente
También me he enfrentado al mismo tipo de problema cuando tuve que analizar un archivo CSV.
El archivo contiene una dirección de columna que contiene el ','.
Después de analizar ese archivo CSV a JSON, obtengo una asignación no coincidente de las claves mientras lo convierto en un archivo JSON.
Solía Node.js para analizar el archivo y bibliotecas como análisis sintáctico bebé y csvtojson .
Ejemplo de archivo -
Mientras analizaba directamente sin usar baby parse en JSON, obtenía:
Entonces escribí un código que elimina la coma (,) con cualquier otro delimitador con cada campo:
La función devuelta se puede pasar a la biblioteca csvtojson y, por lo tanto, se puede usar el resultado.
Ahora puede obtener el resultado como:
fuente
Sin expresiones regulares, legible y de acuerdo con https://en.wikipedia.org/wiki/Comma-separated_values#Basic_rules :
fuente
Según esta publicación de blog , esta función debería hacerlo:
Lo llamarías así:
Este tipo de jsfiddle funciona, pero parece que algunos de los elementos tienen espacios antes.
fuente
"'string, duppi, du', 23, lala"
, esta función devuelve:["'string"," duppi"," du'"," 23"," lala"]
"'"
a'"'
y viceversa.'"string, duppi, du", 23, lala'
da como resultado:['"string',' duppi'.' du"',' 23',' lala']
¡Expresiones regulares al rescate! Estas pocas líneas de código manejan los campos entrecomillados correctamente con comas, comillas y nuevas líneas incrustadas según el estándar RFC 4180.
A menos que se indique en otra parte, no necesita una máquina de estado finito. La expresión regular maneja RFC 4180 correctamente gracias a la búsqueda hacia atrás positiva, la búsqueda hacia atrás negativa y la búsqueda hacia adelante positiva.
Clonar / descargar código en https://github.com/peterthoeny/parse-csv-js
fuente
Aparte de la excelente y completa respuesta de ridgerunner , pensé en una solución muy simple para cuando su backend ejecuta PHP.
Añadir este archivo PHP para backend de su dominio (por ejemplo:
csv.php
)Ahora agregue esta función a su kit de herramientas de JavaScript (creo que debería revisarse un poco para hacer un navegador cruzado).
Le costará una llamada Ajax, pero al menos no duplicará el código ni incluirá ninguna biblioteca externa.
Ref: http://php.net/manual/en/function.str-getcsv.php
fuente
Puede usar papaparse.js como el siguiente ejemplo:
No olvide incluir papaparse.js en la misma carpeta.
fuente