regular - Regex para cadena entre comillas con comillas de escape
regex.escape c# (15)
¿Cómo obtengo la subcadena " It''s big /"problem "
usando una expresión regular?
s = '' function(){ return " It/'s big /"problem "; }'';
Aquí hay uno que funciona tanto con "y" como fácilmente agrega otros al principio.
("|'')(?:///1|[^/1])*?/1
utiliza la referencia inversa (/ 1) coincide exactamente con lo que está en el primer grupo ("o").
Este funciona perfectamente en PCRE y no cae con .
"(.*?[^//])??((////)+)?+"
Explicación:
- Cada cadena citada comienza con Char:
"
; - Puede contener cualquier cantidad de caracteres:.
.*?
{Lazy Match}; terminando con el carácter de no escape[^//]
; - La instrucción (2) es Lazy (!) Opcional porque la cadena puede estar vacía (""). Entonces:
(.*?[^//])??
- Finalmente, cada cadena citada termina con Char (
"
), pero puede ir precedida por un número par de parejas de signos de escape(////)+
; y es codiciosa (!) Opcional:((////)+)?+
{Greedy matching}, ¡la cadena de caracteres puede estar vacía o sin pares de finalización!
Este viene de nanorc.sample disponible en muchas distros de Linux. Se usa para resaltar la sintaxis de las cadenas de estilo C
/"(//.|[^/"])*/"
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 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.
Me enfrenté a un problema similar al tratar de eliminar cadenas entrecomilladas que pueden interferir con el análisis de algunos archivos.
Terminé con una solución de dos pasos que supera a cualquier regex complicada que se te pueda ocurrir:
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.
Según lo provisto por ePharaoh, la respuesta es
/"([^"//]*(//.[^"//]*)*)"/
Para que lo anterior se aplique a las cadenas de comillas simples o dobles, utilice
/"([^"//]*(//.[^"//]*)*)"|/'([^/'//]*(//.[^/'//]*)*)/'/
Si se realiza una búsqueda desde el principio, ¿puede funcionar?
/"((///")|[^//])*/"
Una opción que no se ha tocado antes es:
- Invierta la cuerda.
- Realice la coincidencia en la secuencia invertida.
- Vuelva a invertir las cadenas coincidentes.
Esto tiene la ventaja adicional de poder hacer coincidir correctamente las etiquetas abiertas con escape.
Digamos que tienes la siguiente cadena; String /"this "should" NOT match/" and "this /"should/" match"
Aquí, /"this "should" NOT match/"
no debería coincidir y debería ser "should"
. Además de eso, this /"should/" match
coincidencia /"should/"
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"'']
De acuerdo, ahora para explicar el RegExp. Esta es la expresión regular 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 la forma de la imagen: generado usando el Regulex de Jex
Imagen en github (JavaScript Regular Expression Visualizer). Lo siento, no tengo una reputación lo suficientemente alta como para incluir imágenes, por lo tanto, es solo un enlace por el momento.
Aquí está la esencia 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
Una versión más extensa de https://.com/a/10786066/1794894
/"([^"//]{50,}(//.[^"//]*)*)"|/'[^/'//]{50,}(//.[^/'//]*)*/'|“[^”//]{50,}(//.[^“//]*)*”/
Esta versión también contiene
- Longitud de cita mínima de 50
- Tipo extra de comillas (abrir
“
y cerrar”
)
Uno tiene que recordar que las expresiones regulares no son una bala de plata para todo lo que es string-y. Algunas cosas son más simples de hacer con un cursor y lineal, manual, buscando. Una CFL haría el truco bastante trivial, pero no hay muchas implementaciones de CFL (afaik).
Me revolvió en regexpal y terminé con esta expresión regular: (No me preguntes cómo funciona, apenas lo entiendo aunque lo haya escrito, jaja)
"(([^"//]?(////)?)|(//")+)+"
"(?://"|.)*?"
Alternando el /"
y el .
Pasa sobre las comillas escapadas mientras que el cuantificador vago *?
asegura que no va más allá del final de la cadena entrecomillada. Funciona con las clases .NET Framework RE
/"(?:[^"//]++|//.)*+"/
Tomado directamente del man perlre
en un sistema Linux con Perl 5.22.0 instalado. Como optimización, esta expresión regular usa la forma "posesactiva" 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.
/"(?:[^"//]|//.)*"/
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);
/(["/']).*?(?<!//)(////)*/1/is
debería funcionar con cualquier cadena citada