2012-07-16 13 views
5

que tienen una cadena como esta:¿Cómo hacer coincidir algo con expresiones regulares que no está entre dos caracteres especiales?

a b c a b "a b" b a "a"

¿Cómo combinar con cada a que no es parte de una cadena delimitada por "? Quiero coincidir con todo lo que está en negrita aquí:

un bc un b "ab" b un "a"

quiero reemplazar esos partidos (o más bien eliminar reemplazándolos con una cadena vacía), por lo que eliminar las partes citadas para la coincidencia no funcionará, porque quiero que permanezcan en la cadena. Estoy usando Ruby.

+0

Una expresión regular coincide con una única subcadena por vez. Cómo hacer un bucle de una expresión regular es una característica del lenguaje de alojamiento. ¿Qué idioma estás usando? – tripleee

+0

@tripleee Ruby. –

Respuesta

13

Suponiendo que las cotizaciones están correctamente equilibrados y no hay comillas escapadas, entonces es fácil:

result = subject.gsub(/a(?=(?:[^"]*"[^"]*")*[^"]*\Z)/, '') 

se reemplazan todos los a s con la cadena vacía si y sólo si hay un número par de citas por delante del a coincidente.

Explicación:

a  # Match a 
(?=  # only if it's followed by... 
(?:  # ...the following: 
    [^"]*" # any number of non-quotes, followed by one quote 
    [^"]*" # the same again, ensuring an even number 
)*  # any number of times (0, 2, 4 etc. quotes) 
[^"]* # followed by only non-quotes until 
\Z  # the end of the string. 
)  # End of lookahead assertion 

Si puede haber escapado cotizaciones dentro de comillas (a "length: 2\""), sigue siendo posible, pero será más complicado:

result = subject.gsub(/a(?=(?:(?:\\.|[^"\\])*"(?:\\.|[^"\\])*")*(?:\\.|[^"\\])*\Z)/, '') 

Esto es, en esencia, la misma expresión regular como se indica arriba, solo sustituyendo (?:\\.|[^"\\]) por [^"]:

(?:  # Match either... 
\\. # an escaped character 
|  # or 
[^"\\] # any character except backslash or quote 
)  # End of alternation 
+0

+1 Esta es la respuesta –

+0

Guau, una expresión regular impresionante. Me tomó un tiempo, pero ahora entiendo cómo funciona. :) ¿Por qué el voto a favor? –

0

Solución regex completa para amantes de la expresión regular, sin preocuparse por el rendimiento o la legibilidad del código.

Esta solución asume que no hay sintaxis de escape (con sintaxis de escape, el a en se cuenta como dentro de la cadena).

Pseudocódigo:

processedString = 
    inputString.replaceAll("\\".*?\\"","") // Remove all quoted strings 
       .replaceFirst("\\".*", "") // Consider text after lonely quote as inside quote 

A continuación, puede hacer coincidir el texto que desee en el processedString. Puede eliminar el segundo reemplazo si considera el texto después de la cita solitaria como cita externa.

EDITAR

En Ruby, la expresión regular en el código anterior sería

/\".*?\"/ 

utilizarse con gsub

y

/\".*/ 

se utiliza con sub


Para abordar el problema de reemplazo, no estoy seguro de si esto es posible, pero él valores tratar:

  • declarar un contador
  • Uso la expresión regular /(\"|a)/ con gsub, y función de suministro.
  • En la función, si la coincidencia es ", luego incremente el contador, y devuelva " como reemplazo (básicamente, sin cambios). Si la coincidencia es a compruebe si el contador es par: si incluso suministre su cadena de reemplazo; de lo contrario, solo suministre lo que corresponda.
+0

¿Tiene esto algo que ver con 'a's como se menciona en el requisito OP? –

+0

@ElRonnoco: Sí. En lugar de hacer todo al mismo tiempo, simplemente eliminé toda la cadena entrecomillada y dejé solo las partes no citadas en 'processedString'. Entonces buscar texto será fácil. Mi solución tiene suposición, sin embargo. – nhahtdh

+0

Ah, la idea es que * entonces * usted hace el reemplazo de 'a's ... –

4

js-coder, resucitando esta antigua pregunta porque tenía una solución simple que no se mencionaba. (Encontrado su pregunta mientras se hace un poco de investigación para un regex bounty quest.)

Como se puede ver la expresión regular es muy pequeña en comparación con la expresión regular en la respuesta aceptada: ("[^"]*")|a

subject = 'a b c a b " a b " b a " a "' 
regex = /("[^"]*")|a/ 
replaced = subject.gsub(regex) {|m|$1} 
puts replaced 

ver este live demo

Referencia

How to match pattern except in situations s1, s2, s3

How to match a pattern unless...

Cuestiones relacionadas