¿Cómo se encuentra "Es" en una cadena que solo contiene "Es"? Lo arreglaría por usted, pero no sé qué convenciones de comillas simples / escape se aplican en el idioma que está utilizando.
De hecho, mirando las fechas, veo que la otra pregunta es un duplicado de esta. De cualquier manera, asegúrese de revisar mi respuesta .
ridgerunner
@ridgerunner: Estoy votando para cerrar esto como sugirió. Es cierto que otra pregunta es más reciente, pero también es mucho mejor (gracias principalmente a tu respuesta).
Alan Moore
Respuestas:
160
/"(?:[^"\\]|\\.)*"/
Funciona en The Regex Coach y PCRE Workbench.
Ejemplo de prueba en JavaScript:
var s =' function(){ return " Is big \\"problem\\", \\no? "; }';var m = s.match(/"(?:[^"\\]|\\.)*"/);if(m !=null)
alert(m);
Tiene sentido. Inglés simple: dos comillas alrededor de cero o más de "cualquier carácter que no sea una cita o una barra invertida" o "una barra invertida seguida de cualquier carácter". No puedo creer que no pensé en hacer eso ...
Ajedi32
7
Yo mismo responderé. =) (?:...)es un grupo pasivo o no capturador. Significa que no se puede volver a referenciar posteriormente.
magras
después de buscar mucho y probar mucho, esta es la única solución real que encontré para este problema común. ¡Gracias!
cancerbero
10
gracias por esto. También quería unir comillas simples, así que terminé adaptándolo a esto:/(["'])(?:[^\1\\]|\\.)*?\1/
c.nanorc fue el primer lugar al que fui. No se pudo hacer que funcionara como parte de un literal de cadena C hasta que se escapó doblemente todo como este" \"(\\\\.|[^\\\"])*\" "
hellork
Esto funciona con las funciones egrep y re_comp / re_exec de libc.
fk0
19
Según lo proporcionado por ePharaoh, la respuesta es
/"([^"\\]*(\\.[^"\\]*)*)"/
Para que lo anterior se aplique a cadenas entre comillas simples o dobles, utilice
Este es el único conjunto que me funcionó con una única cadena grande entre comillas de 1,5 KB que contiene 99 escapes. Todas las demás expresiones de esta página se rompieron en mi editor de texto con un error de desbordamiento. Aunque la mayoría aquí funciona en el navegador, algo a tener en cuenta. Fiddle: jsfiddle.net/aow20y0L
Beejor
3
Consulte la respuesta de @ MarcAndrePoulin a continuación para obtener una explicación.
Shaunc
10
La mayoría de las soluciones proporcionadas aquí utilizan rutas de repetición alternativas, es decir (A | B) *.
Puede encontrar desbordamientos de pila en entradas grandes, ya que algunos compiladores de patrones implementan esto usando la recursividad.
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.
Alternando el \"y el .pasa sobre comillas escapadas mientras que el cuantificador perezoso *?asegura que no se pasa del final de la cadena entre comillas. Funciona con clases RE de .NET Framework
Tomado directamente de man perlreun sistema Linux con Perl 5.22.0 instalado. Como optimización, esta expresión regular usa la forma 'posesiva' de ambos +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.
Agradable, pero demasiado flexible para la solicitud (coincidirá con comillas simples ...). Y se puede simplificar a /".*?(?<!\)"/ a menos que me pierda algo. Ah, y algunos lenguajes (por ejemplo, JavaScript) lamentablemente no entienden las expresiones de búsqueda atrás negativas.
PhiLho
1
@PhiLho, solo usar un solo (? <! \\) fallaría en las barras invertidas escapadas al final de la cadena. Sin embargo, es cierto acerca de las búsquedas retrospectivas en JavaScript.
Markus Jarderot
4
Este funciona perfectamente en PCRE y no cae con StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Explicación:
Cada cadena entre comillas se inicia con Char: ";
Puede contener cualquier número de caracteres: .*?{Lazy match}; terminando con carácter sin escape [^\\];
La declaración (2) es Lazy (!) Opcional porque la cadena puede estar vacía (""). Entonces:(.*?[^\\])??
Finalmente, cada cadena entre comillas termina con Char ( "), pero puede ir precedida de un número par de pares de signos de escape (\\\\)+; y es Codicioso (!) opcional: ((\\\\)+)?+{Coincidencia codiciosa}, ¡porque la cadena puede estar vacía o sin pares finales!
esta es una muy buena solución, pero [^\1]debería ser reemplazada .porque no existe tal cosa como una referencia anti-retroceso, y de todos modos no importa. la primera condición siempre coincidirá antes de que suceda algo malo.
Seph Reed
@SephReed - reemplazando [^\1]con .cambiaría de manera efectiva esta expresión regular para ("|').*?\1y luego se igualaría "foo\"en "foo \" bar". Dicho esto, llegar [^\1]a trabajar realmente es difícil. @ Mathiashansen - Está mejor con lo difícil de manejar y caro (?!\1).(por lo que toda la expresión regular, con un poco de limpieza de eficiencia, sería (["'])(?:\\.|(?!\1).)*+\1. +Es opcional si su motor no lo admite.
Adam Katz
2
Una opción que no se ha tocado antes es:
Invierta la cuerda.
Realice la coincidencia en la cuerda invertida.
Vuelva a invertir las cadenas coincidentes.
Esto tiene la ventaja adicional de poder hacer coincidir correctamente las etiquetas abiertas escapadas.
Digamos que tienes la siguiente cadena; String \"this "should" NOT match\" and "this \"should\" match"
Aquí, \"this "should" NOT match\"no debe coincidir y "should"debe ser. Además de eso, this \"should\" matchdebería coincidir y \"should\"no debería.
Primero un ejemplo.
// The input string.const myString ='String \\"this "should" NOT match\\" and "this \\"should\\" match"';// The RegExp.const regExp =newRegExp(// 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 RegExp. Esta es la expresión regular que se puede dividir fácilmente en tres partes. Como sigue:
# 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)
Esto es probablemente mucho más claro en forma de imagen: generado usando Regulex de Jex
Hay que recordar que las expresiones regulares no son una solución milagrosa para todo lo relacionado con las cadenas. Algunas cosas son más sencillas de hacer con un cursor y de búsqueda lineal, manual. Una CFL haría el truco de manera bastante trivial, pero no hay muchas implementaciones de CFL (afaik).
Enfrenté un problema similar al intentar eliminar cadenas entre comillas que pueden interferir con el análisis de algunos archivos.
Terminé con una solución de dos pasos que supera cualquier expresión regular intrincada que se te ocurra:
line = line.replace("\\\"","\'");// Replace escaped quotes with something easier to handle
line = line.replaceAll("\"([^\"]*)\"","\"x\"");// Simple is beautiful
Si su IDE es IntelliJ Idea, puede olvidar todos estos dolores de cabeza y almacenar su expresión regular en una variable de cadena y, a medida que la copia y pega dentro de la comilla doble, automáticamente cambiará a un formato de expresión regular aceptable.
ejemplo en Java:
String s ="\"en_usa\":[^\\,\\}]+";
ahora puedes usar esta variable en tu expresión regular o en cualquier lugar.
Respuestas:
Funciona en The Regex Coach y PCRE Workbench.
Ejemplo de prueba en JavaScript:
fuente
(?:...)
es un grupo pasivo o no capturador. Significa que no se puede volver a referenciar posteriormente./(["'])(?:[^\1\\]|\\.)*?\1/
var s = ' my \\"new\\" string and \"this should be matched\"';
, este enfoque conducirá a resultados inesperados.Este proviene de nanorc.sample disponible en muchas distribuciones de Linux. Se utiliza para resaltar la sintaxis de cadenas de estilo C
fuente
var s = ' my \\"new\\" string and \"this should be matched\"';
, este enfoque conducirá a resultados inesperados." \"(\\\\.|[^\\\"])*\" "
Según lo proporcionado por ePharaoh, la respuesta es
Para que lo anterior se aplique a cadenas entre comillas simples o dobles, utilice
fuente
La mayoría de las soluciones proporcionadas aquí utilizan rutas de repetición alternativas, es decir (A | B) *.
Puede encontrar desbordamientos de pila en entradas grandes, ya que algunos compiladores de patrones implementan esto usando la recursividad.
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.fuente
Alternando el
\"
y el.
pasa sobre comillas escapadas mientras que el cuantificador perezoso*?
asegura que no se pasa del final de la cadena entre comillas. Funciona con clases RE de .NET Frameworkfuente
"\\"
var s = ' my \\"new\\" string and \"this should be matched\"';
/"(?:(?:\\"|[^"])*)"/g
esto debería arreglarTomado directamente de
man perlre
un sistema Linux con Perl 5.22.0 instalado. Como optimización, esta expresión regular usa la forma 'posesiva' de ambos+
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.fuente
debería funcionar con cualquier cadena entre comillas
fuente
Este funciona perfectamente en PCRE y no cae con StackOverflow.
Explicación:
"
;.*?
{Lazy match}; terminando con carácter sin escape[^\\]
;(.*?[^\\])??
"
), pero puede ir precedida de un número par de pares de signos de escape(\\\\)+
; y es Codicioso (!) opcional:((\\\\)+)?+
{Coincidencia codiciosa}, ¡porque la cadena puede estar vacía o sin pares finales!fuente
"(.*?[^\\])?(\\\\)*"
aquí hay uno que funciona con "y" y puede agregar fácilmente otros al principio.
utiliza la referencia inversa (\ 1) que coincide exactamente con lo que está en el primer grupo ("o ').
http://www.regular-expressions.info/backref.html
fuente
[^\1]
debería ser reemplazada.
porque no existe tal cosa como una referencia anti-retroceso, y de todos modos no importa. la primera condición siempre coincidirá antes de que suceda algo malo.[^\1]
con.
cambiaría de manera efectiva esta expresión regular para("|').*?\1
y luego se igualaría"foo\"
en"foo \" bar"
. Dicho esto, llegar[^\1]
a trabajar realmente es difícil. @ Mathiashansen - Está mejor con lo difícil de manejar y caro(?!\1).
(por lo que toda la expresión regular, con un poco de limpieza de eficiencia, sería(["'])(?:\\.|(?!\1).)*+\1
.+
Es opcional si su motor no lo admite.Una opción que no se ha tocado antes es:
Esto tiene la ventaja adicional de poder hacer coincidir correctamente las etiquetas abiertas escapadas.
Digamos que tienes la siguiente cadena;
String \"this "should" NOT match\" and "this \"should\" match"
Aquí,\"this "should" NOT match\"
no debe coincidir y"should"
debe ser. Además de eso,this \"should\" match
debería coincidir y\"should\"
no debería.Primero un ejemplo.
Bien, ahora para explicar la RegExp. Esta es la expresión regular que se puede dividir fácilmente en tres partes. Como sigue:
Esto es probablemente mucho más claro en forma de imagen: generado usando Regulex de Jex
Imagen en github (Visualizador de expresiones regulares de JavaScript). Lo siento, no tengo una reputación lo suficientemente alta como para incluir imágenes, por lo que es solo un enlace por ahora.
Aquí hay un resumen de una función de ejemplo que utiliza este concepto que es un poco más avanzado: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
fuente
Hay que recordar que las expresiones regulares no son una solución milagrosa para todo lo relacionado con las cadenas. Algunas cosas son más sencillas de hacer con un cursor y de búsqueda lineal, manual. Una CFL haría el truco de manera bastante trivial, pero no hay muchas implementaciones de CFL (afaik).
fuente
Una versión más extensa de https://stackoverflow.com/a/10786066/1794894
Esta versión también contiene
“
y cerrar”
)fuente
Me equivoqué en regexpal y terminé con esta expresión regular: (No me preguntes cómo funciona, apenas lo entiendo aunque lo escribí jajaja)
fuente
Si se busca desde el principio, ¿quizás esto funcione?
fuente
Enfrenté un problema similar al intentar eliminar cadenas entre comillas que pueden interferir con el análisis de algunos archivos.
Terminé con una solución de dos pasos que supera cualquier expresión regular intrincada que se te ocurra:
Más fácil de leer y probablemente más eficiente.
fuente
Si su IDE es IntelliJ Idea, puede olvidar todos estos dolores de cabeza y almacenar su expresión regular en una variable de cadena y, a medida que la copia y pega dentro de la comilla doble, automáticamente cambiará a un formato de expresión regular aceptable.
ejemplo en Java:
ahora puedes usar esta variable en tu expresión regular o en cualquier lugar.
fuente