2n-1
, where `n` is the length of the sequence.
+Hay muchas formas de dividir una secuencia de dígitos `123456789` en números. Para ser precisos, hay 2n-1
, donde `n` es la longitud de la secuencia.
-- For `123456789` we have `n=9`, that gives 511 combinations.
-- For a longer sequence with `n=20` there are about one million (1048575) combinations.
-- For `n=30` - a thousand times more (1073741823 combinations).
+- Para `123456789` tenemos `n=9`, lo que da 511 combinaciones.
+- Para una secuencia más larga con "n=20" hay alrededor de un millón (1048575) de combinaciones.
+- Para `n=30` - mil veces más (1073741823 combinaciones).
-Trying each of them is exactly the reason why the search takes so long.
+Probar cada una de ellas es precisamente la razón por la que la búsqueda lleva tanto tiempo.
-## Back to words and strings
+## Volver a las palabras y cadenas
-The similar thing happens in our first example, when we look for words by pattern `pattern:^(\w+\s?)*$` in the string `subject:An input that hangs!`.
+Lo mismo ocurre en nuestro primer ejemplo, cuando buscamos palabras por el patrón `pattern:^(\w+\s?)*$` en la cadena `subject:An input that hangs!`.
-The reason is that a word can be represented as one `pattern:\w+` or many:
+La razón es que una palabra puede representarse como un `pattern:\w+` o muchos:
```
(input)
@@ -172,27 +172,27 @@ The reason is that a word can be represented as one `pattern:\w+` or many:
...
```
-For a human, it's obvious that there may be no match, because the string ends with an exclamation sign `!`, but the regular expression expects a wordly character `pattern:\w` or a space `pattern:\s` at the end. But the engine doesn't know that.
+Para un humano es obvio que puede no haber coincidencia porque la cadena termina con un signo de exclamación `!` pero la expresión regular espera un carácter denominativo `pattern:\w` o un espacio `pattern:\s` al final. Pero el motor no lo sabe.
-It tries all combinations of how the regexp `pattern:(\w+\s?)*` can "consume" the string, including variants with spaces `pattern:(\w+\s)*` and without them `pattern:(\w+)*` (because spaces `pattern:\s?` are optional). As there are many such combinations (we've seen it with digits), the search takes a lot of time.
+El motor prueba todas las combinaciones de cómo la regexp `pattern:(\w+\s?)*` puede "consumir" la cadena, incluyendo las variantes con espacios `pattern:(\w+\s)*` y sin ellos `pattern:(\w+)*` (porque los espacios `pattern:\s?` son opcionales). Como hay muchas combinaciones de este tipo (lo hemos visto con dígitos), la búsqueda lleva muchísimo tiempo.
-What to do?
+¿Qué hacer?
-Should we turn on the lazy mode?
+¿Debemos activar el lazy mode?
-Unfortunately, that won't help: if we replace `pattern:\w+` with `pattern:\w+?`, the regexp will still hang. The order of combinations will change, but not their total count.
+Desgraciadamente eso no ayudará: si sustituimos `pattern:\w+` por `pattern:\w+?` la regexp seguirá colgada. El orden de las combinaciones cambiará, pero no su número total.
-Some regular expression engines have tricky tests and finite automations that allow to avoid going through all combinations or make it much faster, but most engines don't, and it doesn't always help.
+Algunos motores de expresiones regulares hacen análisis complicados y automatizaciones finitas que permiten evitar pasar por todas las combinaciones o hacerlo mucho más rápido, pero la mayoría de los motores no lo hacen. Además, eso no siempre ayuda.
-## How to fix?
+## ¿Cómo solucionarlo?
-There are two main approaches to fixing the problem.
+Hay dos enfoques principales para solucionar el problema.
-The first is to lower the number of possible combinations.
+El primero es reducir el número de combinaciones posibles.
-Let's make the space non-optional by rewriting the regular expression as `pattern:^(\w+\s)*\w*$` - we'll look for any number of words followed by a space `pattern:(\w+\s)*`, and then (optionally) a final word `pattern:\w*`.
+Hagamos que el espacio no sea opcional reescribiendo la expresión regular como `pattern:^(\w+\s)*\w*$` buscaremos cualquier número de palabras seguidas de un espacio `pattern:(\w+\s)*`, y luego (opcionalmente) una palabra final `pattern:\w*`.
-This regexp is equivalent to the previous one (matches the same) and works well:
+Esta regexp es equivalente a la anterior (coincide con lo mismo) y funciona bien:
```js run
let regexp = /^(\w+\s)*\w*$/;
@@ -201,34 +201,34 @@ let str = "An input string that takes a long time or even makes this regex hang!
alert( regexp.test(str) ); // false
```
-Why did the problem disappear?
+¿Por qué ha desaparecido el problema?
-That's because now the space is mandatory.
+Porque ahora el espacio es obligatorio.
-The previous regexp, if we omit the space, becomes `pattern:(\w+)*`, leading to many combinations of `\w+` within a single word
+La regexp anterior, si omitimos el espacio, se convierte en `pattern:(\w+)*`, dando lugar a muchas combinaciones de `\w+` dentro de una misma palabra
-So `subject:input` could be matched as two repetitions of `pattern:\w+`, like this:
+Así, `subject:input` podría coincidir con dos repeticiones de `pattern:\w+` así:
```
\w+ \w+
(inp)(ut)
```
-The new pattern is different: `pattern:(\w+\s)*` specifies repetitions of words followed by a space! The `subject:input` string can't be matched as two repetitions of `pattern:\w+\s`, because the space is mandatory.
+El nuevo patrón es diferente: `pattern:(\w+\s)*` especifica repeticiones de palabras seguidas de un espacio. La cadena `subject:input` no puede coincidir con dos repeticiones de `pattern:\w+\s`, porque el espacio es obligatorio.
-The time needed to try a lot of (actually most of) combinations is now saved.
+Ahora se ahorra el tiempo necesario para probar un montón de combinaciones (en realidad la mayoría).
-## Preventing backtracking
+## Previniendo el backtracking
-It's not always convenient to rewrite a regexp though. In the example above it was easy, but it's not always obvious how to do it.
+Sin embargo no siempre es conveniente reescribir una regexp. En el ejemplo anterior era fácil pero no siempre es obvio cómo hacerlo.
-Besides, a rewritten regexp is usually more complex, and that's not good. Regexps are complex enough without extra efforts.
+Además una regexp reescrita suele ser más compleja y eso no es bueno. Las regexps son suficientemente complejas sin necesidad de esfuerzos adicionales.
-Luckily, there's an alternative approach. We can forbid backtracking for the quantifier.
+Por suerte hay un enfoque alternativo. Podemos prohibir el retroceso para el cuantificador.
-The root of the problem is that the regexp engine tries many combinations that are obviously wrong for a human.
+La raíz del problema es que el motor de regexp intenta muchas combinaciones que son obviamente erróneas para un humano.
-E.g. in the regexp `pattern:(\d+)*$` it's obvious for a human, that `pattern:+` shouldn't backtrack. If we replace one `pattern:\d+` with two separate `pattern:\d+\d+`, nothing changes:
+Por ejemplo, en la regexp `pattern:(\d+)*$` es obvio para un humano que `patrón:+` no debería retroceder. Si sustituimos un `patrón:\d+` por dos `pattern:\d+\d+` separados nada cambia:
```
\d+........
@@ -238,55 +238,55 @@ E.g. in the regexp `pattern:(\d+)*$` it's obvious for a human, that `pattern:+`
(1234)(56789)!
```
-And in the original example `pattern:^(\w+\s?)*$` we may want to forbid backtracking in `pattern:\w+`. That is: `pattern:\w+` should match a whole word, with the maximal possible length. There's no need to lower the repetitions count in `pattern:\w+` or to split it into two words `pattern:\w+\w+` and so on.
+Y en el ejemplo original `pattern:^(\w+\s?)*$` podemos querer prohibir el backtracking en `pattern:\w+`. Es decir: `pattern:\w+` debe coincidir con una palabra entera, con la máxima longitud posible. No es necesario reducir el número de repeticiones en `pattern:\w+` o dividirlo en dos palabras `pattern:\w+\w+` y así sucesivamente.
-Modern regular expression engines support possessive quantifiers for that. Regular quantifiers become possessive if we add `pattern:+` after them. That is, we use `pattern:\d++` instead of `pattern:\d+` to stop `pattern:+` from backtracking.
+Los motores de expresiones regulares modernos admiten cuantificadores posesivos para ello. Los cuantificadores regulares se convierten en posesivos si añadimos `pattern:+` después de ellos. Es decir, usamos `pattern:\d++` en lugar de `pattern:\d+` para evitar que `pattern:+` retroceda.
-Possessive quantifiers are in fact simpler than "regular" ones. They just match as many as they can, without any backtracking. The search process without backtracking is simpler.
+Los cuantificadores posesivos son de hecho más simples que los "regulares". Simplemente coinciden con todos los que pueden sin ningún tipo de retroceso. El proceso de búsqueda sin retroceso es más sencillo.
-There are also so-called "atomic capturing groups" - a way to disable backtracking inside parentheses.
+También existen los llamados "grupos de captura atómicos", una forma de desactivar el retroceso dentro de los paréntesis.
-...But the bad news is that, unfortunately, in JavaScript they are not supported.
+...Pero la mala noticia es que, por desgracia, en JavaScript no están soportados.
-We can emulate them though using a "lookahead transform".
+Sin embargo, podemos emularlos utilizando "lookahead transform".
-### Lookahead to the rescue!
+### Lookahead al rescate!
-So we've come to real advanced topics. We'd like a quantifier, such as `pattern:+` not to backtrack, because sometimes backtracking makes no sense.
+Así que hemos llegado a temas realmente avanzados. Nos gustaría que un cuantificador como `pattern:+` no retrocediera porque a veces retroceder no tiene sentido.
-The pattern to take as many repetitions of `pattern:\w` as possible without backtracking is: `pattern:(?=(\w+))\1`. Of course, we could take another pattern instead of `pattern:\w`.
+El patrón para tomar tantas repeticiones de `pattern:\w` como sea posible sin retroceder es: `pattern:(?=(\w+))\1`. Por supuesto, podríamos tomar otro patrón en lugar de `pattern:\w`.
-That may seem odd, but it's actually a very simple transform.
+Puede parecer extraño pero en realidad es una transformación muy sencilla.
-Let's decipher it:
+Vamos a descifrarla:
-- Lookahead `pattern:?=` looks forward for the longest word `pattern:\w+` starting at the current position.
-- The contents of parentheses with `pattern:?=...` isn't memorized by the engine, so wrap `pattern:\w+` into parentheses. Then the engine will memorize their contents
-- ...And allow us to reference it in the pattern as `pattern:\1`.
+- Lookahead `pattern:?=` busca la palabra más larga `pattern:\w+` a partir de la posición actual.
+- El contenido de los paréntesis con `pattern:?=...` no es memorizado por el motor así que envuelva `pattern:\w+` en paréntesis. Entonces el motor memorizará su contenido
+- ...y nos permitirá hacer referencia a él en el patrón como `pattern:\1`.
-That is: we look ahead - and if there's a word `pattern:\w+`, then match it as `pattern:\1`.
+Es decir: miramos hacia adelante y si hay una palabra `pattern:\w+`, entonces la emparejamos como `pattern:\1`.
-Why? That's because the lookahead finds a word `pattern:\w+` as a whole and we capture it into the pattern with `pattern:\1`. So we essentially implemented a possessive plus `pattern:+` quantifier. It captures only the whole word `pattern:\w+`, not a part of it.
+¿Por qué? Porque el lookahead encuentra una palabra `pattern:\w+` como un todo y la capturamos en el patrón con `pattern:\1`. Así que esencialmente implementamos un cuantificador posesivo más `pattern:+`. Captura sólo la palabra entera `patrón:\w+`, no una parte de ella.
-For instance, in the word `subject:JavaScript` it may not only match `match:Java`, but leave out `match:Script` to match the rest of the pattern.
+Por ejemplo, en la palabra `subject:JavaScript` no sólo puede coincidir con `match:Java` sino que deja fuera `match:Script` para que coincida con el resto del patrón.
-Here's the comparison of two patterns:
+He aquí la comparación de dos patrones:
```js run
alert( "JavaScript".match(/\w+Script/)); // JavaScript
alert( "JavaScript".match(/(?=(\w+))\1Script/)); // null
```
-1. In the first variant `pattern:\w+` first captures the whole word `subject:JavaScript` but then `pattern:+` backtracks character by character, to try to match the rest of the pattern, until it finally succeeds (when `pattern:\w+` matches `match:Java`).
-2. In the second variant `pattern:(?=(\w+))` looks ahead and finds the word `subject:JavaScript`, that is included into the pattern as a whole by `pattern:\1`, so there remains no way to find `subject:Script` after it.
+1. En la primera variante, `pattern:\w+` captura primero la palabra completa `subject:JavaScript`, pero luego `pattern:+` retrocede carácter por carácter, para intentar coincidir con el resto del patrón, hasta que finalmente tiene éxito (cuando `pattern:\w+` coincide con `match:Java`).
+2. En la segunda variante `pattern:(?=(\w+))` mira hacia adelante y encuentra la palabra `subject:JavaScript`, que está incluida en el patrón como un todo por `pattern:\1`, por lo que no hay manera de encontrar `subject:Script` después de ella.
-We can put a more complex regular expression into `pattern:(?=(\w+))\1` instead of `pattern:\w`, when we need to forbid backtracking for `pattern:+` after it.
+Podemos poner una expresión regular más compleja en `pattern:(?=(\w+))\1` en lugar de `pattern:\w`, cuando necesitemos prohibir el retroceso para `pattern:+` después de ella.
```smart
-There's more about the relation between possessive quantifiers and lookahead in articles [Regex: Emulate Atomic Grouping (and Possessive Quantifiers) with LookAhead](http://instanceof.me/post/52245507631/regex-emulate-atomic-grouping-with-lookahead) and [Mimicking Atomic Groups](http://blog.stevenlevithan.com/archives/mimic-atomic-groups).
+Hay más (en inglés) acerca de la relación entre los cuantificadores posesivos y lookahead en los artículos [Regex: Emulate Atomic Grouping (and Possessive Quantifiers) with LookAhead](https://instanceof.me/post/52245507631/regex-emulate-atomic-grouping-with-lookahead) y [Mimicking Atomic Groups](https://blog.stevenlevithan.com/archives/mimic-atomic-groups).
```
-Let's rewrite the first example using lookahead to prevent backtracking:
+Reescribamos el primer ejemplo utilizando lookahead para evitar el backtracking:
```js run
let regexp = /^((?=(\w+))\2\s?)*$/;
@@ -295,13 +295,13 @@ alert( regexp.test("A good string") ); // true
let str = "An input string that takes a long time or even makes this regex hang!";
-alert( regexp.test(str) ); // false, works and fast!
+alert( regexp.test(str) ); // false, funciona, ¡y rápido!
```
-Here `pattern:\2` is used instead of `pattern:\1`, because there are additional outer parentheses. To avoid messing up with the numbers, we can give the parentheses a name, e.g. `pattern:(?Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: