2011-02-07 26 views
7

que estoy haciendo un poco de gimnasia de expresiones regulares. Me propuse la tarea de intentar buscar el código C# donde hay un uso del operador as no seguido por un cheque nulo dentro de una cantidad de espacio razonable. Ahora no quiero analizar el código C#. P.ej. Quiero capturar fragmentos de código comoLas expresiones regulares búsqueda negativa hacia delante

var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1.a == y1.a) 

sin embargo, no capturar

var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1 == null) 

ni por supuesto

var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(somethingunrelated == null) {...} 
    if(x1.a == y1.a) 

Así, cualquier azar nulo cheque contará como un "buen cheque "y por lo tanto no encontrado.

La pregunta es: ¿Cómo hago coincidir algo mientras me aseguro de que no se encuentre algo más en su entorno?

he probado el enfoque ingenuo, en busca de 'como' a continuación, haciendo una búsqueda negativa hacia delante dentro de 150 caracteres.

\bas\b.{1,150}(?!\b==\s*null\b) 

La expresión regular anterior coincide con todos los ejemplos anteriores infortunadamente. Mi instinto me dice, el problema es que el mirar hacia el futuro y luego hacer búsqueda negativa hacia delante puede encontrar muchas situaciones en las que la búsqueda hacia delante no encuentra el '== null'.

Si intento negando toda la expresión, entonces eso no ayuda tampoco, por lo que podría coincidir con la mayoría de código C# alrededor.

+2

¿No puedes usar un analizador C# correcto? – Gumbo

+2

Dije al principio "Estoy haciendo gimnasia de expresión regular. Me propuse la tarea de buscar C#" ... –

+0

¿Es esto como ver fútbol y pensar "es como hacer gimnasia"? :-) – xanatos

Respuesta

11

I amor gimnasia de expresiones regulares! Aquí es una expresión regular PHP comentado:

$re = '/# Find all AS, (but not preceding a XX == null). 
    \bas\b    # Match "as" 
    (?=     # But only if... 
     (?:    # there exist from 1-150 
     [\S\s]   # chars, each of which 
     (?!==\s*null) # are NOT preceding "=NULL" 
    ){1,150}?   # (and do this lazily) 
     (?:    # We are done when either 
     (?=    # we have reached 
      ==\s*(?!null) # a non NULL conditional 
     )    # 
     | $    # or the end of string. 
    ) 
    )/ix' 

Y aquí es en el estilo de Javascript:

re = /\bas\b(?=(?:[\S\s](?!==\s*null)){1,150}?(?:(?===\s*(?!null))|$))/ig; 

Ésta hizo mi cabeza dolía un poco ...

aquí es la prueba de los datos que estoy usando:

text = r""" var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1.a == y1.a) 

however, not capture 
    var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(x1 == null) 

nor for that matter 
    var x1 = x as SimpleRes; 
    var y1 = y as SimpleRes; 
    if(somethingunrelated == null) {...} 
    if(x1.a == y1.a)""" 
+0

Y si desea que funcione con una prueba condicional negativa, p. 'X! = Null', simplemente cambie cada uno:' == 'a:' [! =] = ' – ridgerunner

+0

Muy bien hecho, y buena explicación. +1. Sin embargo, incluiría la advertencia habitual de que Regex no es 100% confiable para analizar C#. –

2

Coloque el .{1,150} dentro de la búsqueda hacia delante, y reemplace . con \s\S (en general, . no coincide con saltos de línea). Además, el \b podría ser engañoso cerca de la ==.

\bas\b(?![\s\S]{1,150}==\s*null\b) 
+0

No puedo hacer que tu idea funcione, todavía incluye el segundo ejemplo anterior en mis resultados de búsqueda. –

+0

Esta expresión regular: '\ bas \ b (?! [\ S \ S] {1,150} == \ s * null \ b)' está bastante cerca, pero no coincide con el segundo AS en el primer conjunto de "debe coincidir" " datos de prueba. – ridgerunner

+0

@ridgerunner ¿funciona para usted con Python? No tengo una configuración de C# para probar. – robert

2

creo que ayudaría a poner el nombre de la variable en() para que pueda utilizarlo como una referencia hacia atrás. Algo similar a lo siguiente,

\b(\w+)\b\W*=\W*\w*\W*\bas\b[\s\S]{1,150}(?!\b\1\b\W*==\W*\bnull\b) 
2

La pregunta no está clara. Qué quieres exactamente ? Lamento, pero todavía no entiendo, después de haber leído la pregunta y los comentarios en numerosas ocasiones.

.

Debe ser el código en C#? En Python? ¿Otro?No hay ninguna indicación sobre este punto

.

¿Desea una coincidencia solo si una línea if(... == ...) sigue un bloque de líneas var ... = ...?

¿O una línea heterogénea puede ENTRE el bloque y la línea if(... == ...) sin detener la coincidencia?

Mi código toma la segunda opción como verdadera.

.

¿Una línea if(... == null) DESPUÉS de una línea if(... == ...) detiene la coincidencia o no?

No se puede entender si es sí o no, definí las dos expresiones regulares para captar estas dos opciones.

.

Espero que mi código sea lo suficientemente claro y responda a su preocupación.

Es en Python

import re 

ch1 ='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 
1618987987849891 
''' 

ch2 ='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
uydtdrdutdutrr 
if(x1.a == y1.a) 
3213546878''' 

ch3='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1 == null) 
165478964654456454''' 

ch4='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
hgyrtdduihudgug 
if(x1 == null) 
165489746+54646544''' 

ch5='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(somethingunrelated == null) {...} 
if(x1.a == y1.a) 
1354687897''' 

ch6='''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
ifughobviudyhogiuvyhoiuhoiv 
if(somethingunrelated == null) {...} 
if(x1.a == y1.a) 
2468748874897498749874897''' 

ch7 = '''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 
iufxresguygo 
liygcygfuihoiuguyg 
if(somethingunrelated == null) {...} 
oufxsyrtuy 
''' 

ch8 = '''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 
iufxresguygo 
liygcygfuihoiuguyg 
if(somethingunrelated == null) {...} 
oufxsyrtuy 
''' 

ch9 = '''kutgdfxfovuyfuuff 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 
if(somethingunrelated == null) {...} 
oufxsyrtuy 
''' 

pat1 = re.compile(('(' 
        '(^var +\S+ *= *\S+ +as .+[\r\n]+)+?' 
        '([\s\S](?!==\s*null\\b))*?' 
        '^if *\(*[^\s=]+ *==(?!\s*null).+$' 
        ')' 
        ), 
        re.MULTILINE) 

pat2 = re.compile(('(' 
        '(^var +\S+ *= *\S+ +as .+[\r\n]+)+?' 
        '([\s\S](?!==\s*null\\b))*?' 
        '^if *\(*[^\s=]+ *==(?!\s*null).+$' 
        ')' 
        '(?![\s\S]{0,150}==)' 
        ), 
        re.MULTILINE) 


for ch in (ch1,ch2,ch3,ch4,ch5,ch6,ch7,ch8,ch9): 
    print pat1.search(ch).group() if pat1.search(ch) else pat1.search(ch) 
    print 
    print pat2.search(ch).group() if pat2.search(ch) else pat2.search(ch) 
    print '-----------------------------------------' 

Resultado

>>> 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 

var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
uydtdrdutdutrr 
if(x1.a == y1.a) 

var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
uydtdrdutdutrr 
if(x1.a == y1.a) 
----------------------------------------- 
None 

None 
----------------------------------------- 
None 

None 
----------------------------------------- 
None 

None 
----------------------------------------- 
None 

None 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
if(x1.a == y1.a) 

None 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 

None 
----------------------------------------- 
var x1 = x as SimpleRes; 
var y1 = y as SimpleRes; 
tfsezfuytfyfy 
if(x1.a == y1.a) 

None 
----------------------------------------- 
>>> 
+0

+1 Acepto que la pregunta es bastante vaga. La mayoría de las personas no entienden que una buena pregunta de expresiones regulares debe ser explicada de manera muy precisa. – ridgerunner

2

Voy a tratar de redefinir su problema:

  1. Busque un "como" asignación - es probable que necesita una Mejor expresión regular para buscar asignaciones reales y puede querer almacenar la expresión asignada, pero usemos "\ bas \ b" por ahora
  2. Si ve un if (... == null) dentro de 150 caracteres, no coinciden con
  3. Si no ve una if (... == null) dentro de 150 caracteres, partido

Su expresión \bas\b.{1,150}(?!\b==\s*null\b) no funcionará debido a la negativa Mira- adelante. La expresión regular siempre puede omitir una letra hacia adelante o hacia atrás para evitar esta mirada negativa hacia adelante y termina emparejando incluso cuando hay un if (... == null) ahí.

Regex no son realmente buenos en no haciendo coincidir algo. En este caso, es mejor tratar de coincidir con un "como" asignación con un "si nula ==" cheque dentro de 150 caracteres:

\bas\b.{1,150}\b==\s*null\b 

y luego negando el cheque: if (!regex.match(text)) ...

1
(?s:\s+as\s+(?!.{0,150}==\s*null\b)) 

Estoy activando la opción SingleLine con ?s:. Puede ponerlo en las opciones de su Regex si lo desea. Añadiré que estoy poniendo \s alrededor de as porque creo que solo los espacios son "legales" alrededor del as. Es probable que pueda poner el \b como

(?s:\b+as\b(?!.{0,150}==\s*null\b)) 

Sé consciente de que \s probablemente coger espacios que no son válidos "espacios".Se define como [\f\n\r\t\v\x85\p{Z}] donde \p{Z} es Unicode Characters in the 'Separator, Space' Category más Unicode Characters in the 'Separator, Line' Category más Unicode Characters in the 'Separator, Paragraph' Category.

Cuestiones relacionadas