2012-04-29 13 views
5

Estoy analizando texto que es muchas repeticiones de un patrón simple. El texto está en el formato de un guión para una obra de teatro, así:Expresión regular para unir todos los caracteres hasta la próxima coincidencia

SAMPSON 
I mean, an we be in choler, we'll draw. 

GREGORY 
Ay, while you live, draw your neck out o' the collar. 

Actualmente estoy usando el patrón ([A-Z0-9\s]+)\s*\:?\s*[\r\n](.+)[\r\n]{2}, que funciona bien (la explicación más abajo) a excepción de cuando el discurso del personaje tiene saltos de línea en ella . Cuando eso sucede, el nombre del personaje se captura con éxito, pero solo se captura la primera línea del discurso.

Al activar el modo de línea única (para incluir saltos de línea en .) se crea una coincidencia gigante.

¿Cómo puedo decirle al (.+) que pare cuando encuentra el siguiente nombre de personaje y finaliza la coincidencia?
Estoy iterando sobre cada coincidencia individualmente (JavaScript), por lo que el nombre debe estar disponible para la próxima coincidencia.

Idealmente, podría hacer coincidir todos los caracteres hasta que se repita todo el patrón.


Patrón explicó:

El primer grupo coincide con el nombre de un personaje (que permite letras mayúsculas, números y espacios en blanco), (con dos puntos de fuga y el espacio en blanco opcional).
El segundo grupo (discurso del personaje) comienza en una nueva línea y captura cualquier carácter (excepto, problemáticamente, saltos de línea y caracteres después de ellos).
El patrón termina (y comienza de nuevo) después de una línea en blanco.

+0

Es necesario definir de manera inequívoca cómo se determina en el siguiente nombre comienza antes de que pueda decreto judicial e una expresión regular para unirla. ¿Es una palabra única seguida de dos puntos en una línea sola? ¿Eso daría lugar a cualquier coincidencia incorrecta? – mellamokb

+0

@mellamokb Olvidé incluir la última parte del patrón, que busca una línea en blanco. El partido comienza con el nombre del personaje (todas las mayúsculas en su propia línea) y termina en la línea en blanco después del discurso. – Nathan

+0

Creo que faltan dos puntos en el texto de muestra, la expresión regular no funciona. –

Respuesta

0

De acuerdo, hice algunos pequeños ajustes y encontré algo que funciona. No es súper elegante, pero cumple su función.

([A-Z0-9\s]+)\s*\:?\s*[\r\n]((.+[\r\n]?.*)+)[\r\n]{2} 

he modificado el último grupo de captura para permitir interminables repeticiones de texto arbitrario, una nueva línea, y el texto más arbitraria. Como no se permiten dos saltos de línea consecutivos, el patrón finaliza después del discurso.

+0

Solo quería señalar, pegué la expresión regular y el ejemplo de su pregunta en [una herramienta de prueba de expresiones regulares] (http://gskinner.com/RegExr/) y luego simplemente habilité el modo * dotall * (puntos coinciden con las líneas nuevas) que resolvió tu problema. Es extraño que no funcionó para usted – Hubro

1

Considera ir en otra dirección con esto. Realmente desea dividir un diálogo más grande en cualquier línea que contenga un nombre. Usted puede hacer esto con una expresión regular todavía (sustituir la expresión regular con lo que coincidirá con la línea de "altavoz"):

results = "Insert script here".split(/^([A-Z]+)$/) 

En unas normas aplicación compatible, es un ejemplo de texto va a terminar en una matriz de este modo:

results[0] = "" 
results[1] = "SAMPSON"  
results[2] = "I mean, an we be in choler, we'll draw.    
" 
results[3] = "GREGORY"  
results[4] = "Ay, while you live, draw your neck out o' the collar. " 

Una advertencia es que la mayoría de los navegadores son irregulares en el estándar aquí. Puede usar la biblioteca XRegExp para obtener un comportamiento de plataforma cruzada.

+0

En mi caso de uso, dividir diálogos en líneas separadas no tiene sentido. Como el programa (y el usuario) interactúa con los diálogos como un todo, simplemente tendría que unirlos de nuevo para que sean útiles. – Nathan

0

Finalmente logré que coincida solo con lo que quería, es decir
- el nombre del personaje, lo que permite espacios en blanco y el colon
- y, dado el caso de varias líneas con saltos de línea, el texto asociado a la persona

que tendría que hacer findAll el uso de esta expresión regular - es entre mayúsculas y minúsculas:

((?:[A-Z]{2,}\s*:?\s*)+)\s+((?![A-Z]{2,}\s*:?\s*).+?[.?!]\s*)+ 

Explicación:

  • ((?:[A-Z]{2,}\s*:?\s*)+) - el primer grupo capta el nombre en mayúsculas de la persona - es coincidirá 'Gregor', así como 'Manfred LA MAYOR:'
  • \s+ - al menos un carácter de espacio en blanco
    luego repetir al menos una vez:
  • (?![A-Z]{2,}\s*:?\s*) - mirar hacia adelante para comprobar que el siguiente texto no es el superior nombre del personaje caso
  • .+?[.?!]\s* - coincidir con todo hasta que encuentre un personaje que termina una sentencia [.?!] y opcionalmente espacios en blanco
Cuestiones relacionadas