2009-08-11 12 views
6

Me gustaría probar si una expresión regular coincidirá con parte de una cadena en un índice específico (y solo a partir de ese índice específico). Por ejemplo, dada la cadena "one two 3 4 five", me gustaría saber que, en el índice 8, la expresión regular [0-9] + coincidirá con "3". RegularExpression.IsMatch y Match ambos toman un índice inicial, sin embargo ambos buscarán el resto de la cadena para una coincidencia si es necesario.C# coincidencia de expresión regular en el índice específico en la cadena?

string text="one two 3 4 five"; 
Regex num=new Regex("[0-9]+"); 

//unfortunately num.IsMatch(text,0) also finds a match and returns true 
Console.WriteLine("{0} {1}",num.IsMatch(text, 8),num.IsMatch(text,0)); 

Obviamente, yo pueda comprobar si el partido resultante comienza en el índice Me interesa, pero me va a hacer de este un gran número de veces en las grandes cadenas, por lo que no quieren perder el tiempo buscando para los partidos más adelante en la cadena. Además, no sabré de antemano qué expresiones regulares voy a probar contra la cadena.

no quiero a:

  1. dividir la cadena de alguna frontera como espacios en blanco porque en mi situación no voy a saber de antemano lo que un límite adecuado sería
  2. tienen que modificar la cadena de entrada en ninguna manera (como conseguir la subcadena en el índice 8 y luego usando^en el expresiones regulares)
  3. buscar en el resto de la cadena de una estera haga o haga cualquier cosa que no sea eficaz para una gran cantidad de pruebas contra una cadena grande .

Me gustaría analizar un cuerpo de texto potencialmente grande proporcionado por el usuario mediante una gramática arbitraria suministrada por el usuario. La gramática se definirá en una sintaxis similar a BNF o PEG, y los terminales serán cadenas literales o expresiones regulares. Por lo tanto, tendré que comprobar si la siguiente parte de la cadena coincide con cualquiera de los terminales potenciales según lo determine la gramática.

+1

¿Puede explicar lo que está tratando de hacer en un sentido más amplio? Sus restricciones sobre lo que no quiere hacer son confusas. –

+0

Agregué una breve descripción de lo que estoy haciendo. Además, los requisitos realmente se reducen a: no quiero hacer nada lento y no tengo un conocimiento profundo de lo que estoy tratando de analizar desde el principio. – Rngbus

Respuesta

11

¿Qué le parece usar Regex.IsMatch(string, int) usando una expresión regular que comienza con \G (significando "inicio de la última coincidencia")?

Eso parece funcionar:

using System; 
using System.Text.RegularExpressions; 

class Test 
{ 
    static void Main() 
    { 
     string text="one two 3 4 five"; 
     Regex num=new Regex(@"\G[0-9]+"); 

     Console.WriteLine("{0} {1}", 
          num.IsMatch(text, 8), // True 
          num.IsMatch(text, 0)); // False 
    } 
} 
+0

Interesante, si hay una manera de establecer artificialmente la posición del último partido, entonces esto podría funcionar. De lo contrario, no creo que sea de ayuda, ya que estaré saltando entre diferentes expresiones regulares y diferentes ubicaciones. – Rngbus

+0

Tuve la oportunidad de probar esto y parece hacer exactamente lo que quiero. Trata el índice de inicio aprobado como el "inicio del último partido" sin importar dónde estuvo realmente el último partido. ¡Perfecto gracias! – Rngbus

+2

Y solo para agregar un poco de información para cualquier otra persona que tenga este problema, http://www.regular-expressions.info/continue.html describe el anclaje \ G. Parece significar "inicio del último partido" o "inicio del intento de coincidencia" según la implementación. En algunas implementaciones, probablemente no resolverá este problema, pero parece ser un "intento de inicio de partida" en C# y funciona muy bien para hacer correspondencias en una ubicación específica. – Rngbus

2

Si sólo desea buscar una subcadena del texto, agarrar esa subcadena antes de la expresión regular.

myRegex.Match(myString.Substring(8, 10)); 
+2

Ver el punto 2 en la pregunta. –

+0

No parece que esto modifique la cadena de entrada, por lo tanto, +1. Si el punto 2 no se trata solo de cambiar la cadena de entrada, necesita ser editado. – ojrac

+1

Bueno, está modificando la entrada * a la expresión regular *. Dado el "hacer esto una gran cantidad de veces en grandes cadenas", no hubiera pensado que una subcadena era una solución ideal. –

1

No estoy seguro de entender completamente la pregunta, pero me parece que sólo tiene que hacer la parte de la posición de la expresión regular, por ejemplo,

^.{8}[\d] 

que coincidirá si hay 8 caracteres entre el inicio de la cadena y un dígito.

+1

Esto no es ideal, porque implicaría modificar la expresión regular para cada posición que quiero probar. También dependería de que la expresión regular sea lo suficientemente inteligente como para optimizar ^. {8} en algo que salte inmediatamente a la posición 8. – Rngbus

0

Si conoce la longitud máxima de una posible coincidencia en la cadena que marca, esto limitaría el escaneo de la cadena.

Si solo está buscando números, probablemente sea más fácil que si busca expresiones arbitrarias. La naturaleza de Regex es escanear hasta el final para encontrar una coincidencia. Si desea evitar el escaneo, debe incluir una longitud o usar algo que no sea Regex.

string text = "one two 3 4 five"; 
Regex num = new Regex("[0-9]+"); 
int indexToCheck = 8; 
int maxMatchLength = ...; 
Match m = num.Match(text, indexToCheck, maxMatchLength); 

¿Sabe usted algo acerca de qué tipos de expresiones que podría funcionar contra las cuerdas, y el análisis de toda la cadena de ser demasiado de una sobrecarga?

num.Match devolverá el primer acierto, si existe, y luego dejará de escanear. Si quiere más coincidencias, debe llamar a m.NextMatch() para continuar escaneando las coincidencias.

+0

Lamentablemente no sé cuáles serán las expresiones regulares de antemano y no puedo proporcionar una longitud máxima aparte del resto de la cuerda. – Rngbus

+0

La expresión para encontrar podría tener una duración variable, dependiendo del espacio en blanco, p. Ej. nuevas líneas y comienzo de párrafo sangrado, o lo que sea. – ProfK

Cuestiones relacionadas