¿Cómo obtengo la subcadena " It's big \"problem "
usando una expresión regular?
s = ' function(){ return " It\'s big \"problem "; }';
¿Cómo obtengo la subcadena " It's big \"problem "
usando una expresión regular?
s = ' function(){ return " It\'s big \"problem "; }';
Respuestas:
/"(?:[^"\\]|\\.)*"/
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);
(?:...)
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
\"(\\.|[^\"])*\"
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
/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
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.
/"(?:[^"\\]++|\\.)*+"/
Tomado 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.
/(["\']).*?(?<!\\)(\\\\)*\1/is
debería funcionar con cualquier cadena entre comillas
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!"(.*?[^\\])?(\\\\)*"
aquí hay uno que funciona con "y" y puede agregar fácilmente otros al principio.
("| ') (?: \\\ 1 | [^ \ 1]) *? \ 1
utiliza la referencia inversa (\ 1) que coincide exactamente con lo que está en el primer grupo ("o ').
[^\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.
// 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 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
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
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).
Una versión más extensa de https://stackoverflow.com/a/10786066/1794894
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
Esta versión también contiene
“
y cerrar ”
)Me equivoqué en regexpal y terminé con esta expresión regular: (No me preguntes cómo funciona, apenas lo entiendo aunque lo escribí jajaja)
"(([^"\\]?(\\\\)?)|(\\")+)+"
Si se busca desde el principio, ¿quizás esto funcione?
\"((\\\")|[^\\])*\"
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
Más fácil de leer y probablemente más eficiente.
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.