2008-10-30 90 views
81

¿Cómo obtengo la subcadena " It's big \"problem " usando una expresión regular?Regex para cadena entre comillas con comillas de escape

s = ' function(){ return " It\'s big \"problem "; }';  
+1

¿Cómo se encuentra "Es" en una cadena que sólo contiene "Es"? Lo arreglaría por ti, pero no sé qué convenciones de cita única/escape se aplican en el idioma que estás usando. –

+0

Duplicado de: [PHP: Regex para ignorar citas escapadas entre comillas] (http://stackoverflow.com/q/5695240) – ridgerunner

+2

En realidad, mirando las fechas, veo que la otra pregunta es un duplicado de esta. De cualquier manera, asegúrese de verificar [mi respuesta] (http://stackoverflow.com/questions/5695240/php-regex-to-ignore-escaped-quotes-within-quotes/5696141#5696141). – ridgerunner

Respuesta

3
/(["\']).*?(?<!\\)(\\\\)*\1/is 

debería funcionar con cualquier cadena entre comillas

+1

Agradable, pero demasiado flexible para la solicitud (coincidirá con comillas simples ...). Y se puede simplificar a /".*?(? PhiLho

+1

@PhiLho, solo con una sola (?

0

Hay que recordar que las expresiones regulares no son una panacea para todo, cuerdas-y. Algunas cosas son más simples de hacer con un cursor y lineal, manual, buscando. Un CFL haría el truco bastante trivial, pero no hay muchas implementaciones de CFL (afaik).

+3

Cierto, pero este problema está dentro de las capacidades de expresiones regulares, y hay muchas implementaciones de esas. –

103
/"(?:[^"\\]|\\.)*"/ 

Trabaja en The Regex Coach and PCRE Workbench.

Ejemplo de prueba en JavaScript:

var s = ' function(){ return " Is big \\"problem\\", \\no? "; }'; 
 
    var m = s.match(/"(?:[^"\\]|\\.)*"/); 
 
    if (m != null) 
 
     alert(m);

+0

Funciona como un amuleto – MaX

+14

Tiene sentido. Inglés llano: dos citas que rodean cero o más de "cualquier carácter que no sea una comilla o una barra invertida" o "una barra invertida seguida de cualquier carácter". No puedo creer que no pensé en hacer eso ... – Ajedi32

+0

¿Qué significa '?:'? – magras

23

Éste viene de nanorc.sample disponible en muchas distribuciones de Linux. Se utiliza para resaltar la sintaxis de cadenas estilo C

\"(\\.|[^\"])*\" 
+0

genial! Funciona bien con la cita de "!!! – LINKeRxUA

+0

Con ['var s = 'my \\" new \\ "string y \" esto debe coincidir con \ "';'] (https://jsfiddle.net/kmyxv9hj/1/), este enfoque conducirá a resultados inesperados. –

+0

Muchas gracias. Realmente me ayudó a no tener que reinventar la rueda. – Beezer

7
"(?:\\"|.)*?" 

alternando la \" y la . pasa por encima de las cotizaciones escapó mientras que el cuantificador perezoso *? se asegura de que usted no va más allá del final de la cadena entre comillas. Funciona con clases de .NET Framework RE

+0

Pero falla con '" \\ "' – Ian

+0

[Fallará con 'var s = 'my \\" new \\ "string y \" esto debería coincidir con \ "';'] (https: // jsfiddle. net/kmyxv9hj/2 /) –

13

Como proporcionada por ePharaoh, la respuesta es

/"([^"\\]*(\\.[^"\\]*)*)"/ 

Para que lo anterior se aplica a cualquiera de las cadenas entre comillas simples o dobles citados, utilice

/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/ 
+1

Este es el único conjunto que funcionó para mí con una única cadena larga de 1.5 KB que contiene 99 escapes. Cualquier otra expresión en esta página se rompió en mi editor de texto con un error de desbordamiento. Aunque la mayoría aquí funciona en el navegador, solo hay que tener en cuenta. Fiddle: https://jsfiddle.net/aow20y0L/ – Beejor

+2

Consulte la respuesta de @ MarcAndrePoulin a continuación para obtener una explicación. – shaunc

0

Si se busca desde el principio, tal vez esto puede funcionar?

\"((\\\")|[^\\])*\" 
0

Una versión más extensa de https://stackoverflow.com/a/10786066/1794894

/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/ 

Esta versión también contiene

  1. longitud cotización mínimo de 50
  2. tipo adicional de comillas (abierta y cerca )
0

en mal estado en torno al regexpal y terminó con esta expresión regular: (No me pregunte cómo funciona, yo apenas entiendo incluso aunque lo escribí lol)

"(([^"\\]?(\\\\)?)|(\\")+)+" 
7

La mayoría de las soluciones proporcionadas aquí usar la repetición alternativa caminos ie (A | B) *.

Puede encontrar desbordamientos de pila en entradas grandes, ya que algunos compiladores de patrones implementan esto mediante la recursión.

Java por ejemplo: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993

Algo como esto: "(?:[^"\\]*(?:\\.)?)*", o el proporcionado por Guy Bedford reducirá la cantidad de pasos de análisis evitando la mayoría de los desbordamientos de pila.

5
/"(?:[^"\\]++|\\.)*+"/ 

llevaron directamente a partir man perlre en un sistema Linux con Perl 5.22.0 instalado. Como optimización, esta expresión regular usa la forma 'posessive' de + y * para evitar el retroceso, ya que se sabe de antemano que una cadena sin una cita de cierre no coincidiría en ningún caso.

3

Este funciona perfectamente en PCRE y no cae con StackOverflow.

"(.*?[^\\])??((\\\\)+)?+" 

Explicación:

  1. Cada cadena entre comillas se inicia con Char: ";
  2. Puede contener cualquier número de caracteres: .*? {Lazy match}; terminando con el carácter de no escape [^\\];
  3. La instrucción (2) es Lazy (!) Opcional porque la cadena puede estar vacía (""). Entonces: (.*?[^\\])??
  4. Finalmente, cada cadena citada termina con Char ("), pero puede ir precedida por un número par de parejas de signos de escape (\\\\)+; y es codicioso (!) opcional: ((\\\\)+)?+ {Greedy matching}, ¡porque la cadena puede estar vacía o sin pares de finalización!
1

aquí es uno que trabaja tanto con "y" y se agrega fácilmente a otros en la salida.

("|')(?:\\\1|[^\1])*?\1

se utiliza la referencia inversa (\ 1) partido exactley lo que está en el primer grupo (" o ').

http://www.regular-expressions.info/backref.html

+0

esta es una muy buena solución, pero '[^ \ 1]' debería reemplazarse por '.' porque no existe una referencia anti-retroactiva, y no importa de todos modos. la primera condición siempre coincidirá antes de que algo malo pueda pasar. –

0

Una opción que no ha sido tocado antes es:

  1. reversa de la cadena.
  2. Realice la coincidencia en la cadena invertida.
  3. Vuelva a invertir las cadenas coincidentes.

Esto tiene la ventaja añadida de ser capaz de igualar correctamente las etiquetas abiertas escapado.

Supongamos que tiene la siguiente cadena; String \"this "should" NOT match\" and "this \"should\" match" Aquí, \"this "should" NOT match\" no debe coincidir y "should" debería ser. Además de eso, this \"should\" match debe coincidir y \"should\" no.

Primero un ejemplo.

// The input string. 
const myString = 'String \\"this "should" NOT match\\" and "this \\"should\\" match"'; 

// The RegExp. 
const regExp = new RegExp(
    // Match close 
    '([\'"])(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))' + 
    '((?:' + 
     // Match escaped close quote 
     '(?:\\1(?=(?:[\\\\]{2})*[\\\\](?![\\\\])))|' + 
     // Match everything thats not the close quote 
     '(?:(?!\\1).)' + 
    '){0,})' + 
    // Match open 
    '(\\1)(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))', 
    'g' 
); 

// Reverse the matched strings. 
matches = myString 
    // Reverse the string. 
    .split('').reverse().join('') 
    // '"hctam "\dluohs"\ siht" dna "\hctam TON "dluohs" siht"\ gnirtS' 

    // Match the quoted 
    .match(regExp) 
    // ['"hctam "\dluohs"\ siht"', '"dluohs"'] 

    // Reverse the matches 
    .map(x => x.split('').reverse().join('')) 
    // ['"this \"should\" match"', '"should"'] 

    // Re order the matches 
    .reverse(); 
    // ['"should"', '"this \"should\" match"'] 

Bien, ahora para explicar la expresión regular. Esta es la expresión regular se puede dividir fácilmente en tres partes. En la siguiente manera:

# Part 1 
(['"])   # Match a closing quotation mark " or ' 
(?!   # As long as it's not followed by 
    (?:[\\]{2})* # A pair of escape characters 
    [\\]   # and a single escape 
    (?![\\])  # As long as that's not followed by an escape 
) 
# Part 2 
((?:   # Match inside the quotes 
(?:   # Match option 1: 
    \1   # Match the closing quote 
    (?=   # As long as it's followed by 
    (?:\\\\)* # A pair of escape characters 
    \\  # 
    (?![\\]) # As long as that's not followed by an escape 
)   # and a single escape 
)|   # OR 
(?:   # Match option 2: 
    (?!\1).  # Any character that isn't the closing quote 
) 
)*)   # Match the group 0 or more times 
# Part 3 
(\1)   # Match an open quotation mark that is the same as the closing one 
(?!   # As long as it's not followed by 
    (?:[\\]{2})* # A pair of escape characters 
    [\\]   # and a single escape 
    (?![\\])  # As long as that's not followed by an escape 
) 

Esta es probablemente mucho más clara en forma de imagen: generada usando Jex's Regulex

Image on github (JavaScript Regular Expression Visualizer.) Lo sentimos, no tengo una reputación lo suficientemente alto como para incluir las imágenes, por lo que, es sólo una enlace por ahora.

Aquí está una esencia de una función de ejemplo utilizando este concepto de que es un poco más avanzado: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js

Cuestiones relacionadas