Skip to content

Sticky flag "y", searching at position #424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Dec 17, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 38 additions & 41 deletions 9-regular-expressions/16-regexp-sticky/article.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,56 @@

# Sticky flag "y", searching at position
# Indicador adhesivo “y”, buscando en una posición.

The flag `pattern:y` allows to perform the search at the given position in the source string.
EL indicador `pattern:y` permite realizar la búsqueda en una posición dada en el string de origen.

To grasp the use case of `pattern:y` flag, and see how great it is, let's explore a practical use case.
Para entender el caso de uso del indicador `pattern:y`, y ver lo notable que es, exploremos un ejemplo práctico.

One of common tasks for regexps is "lexical analysis": we get a text, e.g. in a programming language, and analyze it for structural elements.
Una tarea común para regexps es el "Análisis léxico": tenemos un texto, por ej. en un lenguaje de programación, y analiza sus elementos estructurales.

For instance, HTML has tags and attributes, JavaScript code has functions, variables, and so on.
Por ejemplo, HTML tiene etiquetas y atributos, el código JavaScript tiene funciones, variables, etc.

Writing lexical analyzers is a special area, with its own tools and algorithms, so we don't go deep in there, but there's a common task: to read something at the given position.
Escribir analizadores léxicos es un área especial, con sus propias herramientas y algoritmos, así que no profundizaremos en ello; pero existe una tarea común: leer algo en una posición dada.

E.g. we have a code string `subject:let varName = "value"`, and we need to read the variable name from it, that starts at position `4`.
Por ej. tenemos una cadena de código `subject:let varName = "value"`, y necesitamos leer el nombre de su variable, que comienza en la posición `4`.

We'll look for variable name using regexp `pattern:\w+`. Actually, JavaScript variable names need a bit more complex regexp for accurate matching, but here it doesn't matter.
Buscaremos el nombre de la variable usando regexp `pattern:\w+`. En realidad, el nombre de la variable de JavaScript necesita un regexp un poco más complejo para un emparejamiento más preciso, pero aquí eso no importa.

- A call to `str.match(/\w+/)` will find only the first word in the line (`let`). That's not it.
- We can add the flag `pattern:g`. But then the call `str.match(/\w+/g)` will look for all words in the text, while we need one word at position `4`. Again, not what we need.
Una llamada a `str.match(/\w+/)` solo encontrará la primera palabra de la línea, o todas las palabras con el indicador `pattern:g`. Pero solo necesitamos una palabra en la posición `4`.

**So, how to search for a regexp exactly at the given position?**
Para buscar desde la posición dada, usamos el método `regexp.exec(str)`.

To search from the given position, we can use method `regexp.exec(str)`.
Sí `regexp` no tiene indicadores `pattern:g` o `pattern:y`, entonces este método busca la primera coincidencia en el string `str`, exactamente como `str.match(regexp)`. Un caso tan simple sin indicadores no nos interesa aquí.

If the `regexp` doesn't have flags `pattern:g` or `pattern:y`, then this method looks for the first match in the string `str`, exactly like `str.match(regexp)`. Such simple no-flags case doesn't interest us here.
Si existe el indicador `pattern:g`, realiza la búsqueda en el string `str` empezando desde la posición almacenada en su propiedad `regexp.lastIndex`. Y si encuentra una coincidencia, establece `regexp.lastIndex` en el index inmediatamente después del emparejamiento.

If there's flag `pattern:g`, then it performs the search in the string `str`, starting from position stored in its `regexp.lastIndex` property. And, if it finds a match, then sets `regexp.lastIndex` to the index immediately after the match.
Cuando un regex es creado, su `lastIndex` es `0`.

When a regexp is created, its `lastIndex` is `0`.
Entonces, llamadas sucesivas a `regexp.exec(str)` devuelve coincidencias una después de la otra.

So, successive calls to `regexp.exec(str)` return matches one after another.

An example (with flag `pattern:g`):
Un ejemplo (con el indicador `pattern:g`):

```js run
let str = 'let varName';

let regexp = /\w+/g;
alert(regexp.lastIndex); // 0 (initially lastIndex=0)
alert(regexp.lastIndex); // 0 (inicialmente lastIndex=0)

let word1 = regexp.exec(str);
alert(word1[0]); // let (1st word)
alert(regexp.lastIndex); // 3 (position after the match)
alert(word1[0]); // let (primera palabra)
alert(regexp.lastIndex); // 3 (Posición posterior al emparejamiento)

let word2 = regexp.exec(str);
alert(word2[0]); // varName (2nd word)
alert(regexp.lastIndex); // 11 (position after the match)
alert(word2[0]); // varName (2da palabra)
alert(regexp.lastIndex); // 11 (Posición posterior al emparejamiento)

let word3 = regexp.exec(str);
alert(word3); // null (no more matches)
alert(regexp.lastIndex); // 0 (resets at search end)
alert(word3); // null (no más emparejamientos)
alert(regexp.lastIndex); // 0 (reinicia en el final de la búsqueda)
```

Every match is returned as an array with groups and additional properties.
Cada coincidencia es devuelta como un array con grupos y propiedades adicionales.

We can get all matches in the loop:
Podemos conseguir todas las coincidencias en el loop:

```js run
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

¿Podrias traducir comentarios lineas 63 64 ?
github no me deja sugerir ahi (dentro de un bloque sin traducir)

Quizas tambien la 62 pero con cuidado:

alert( Se encontró ${result[0]} en la posición ${result.index} );

let str = 'let varName';
Expand All @@ -68,16 +65,16 @@ while (result = regexp.exec(str)) {
}
```

Such use of `regexp.exec` is an alternative to method `str.matchAll`.
Tal uso de `regexp.exec` es una alternativa al método `str.match bAll`.

Unlike other methods, we can set our own `lastIndex`, to start the search from the given position.
A diferencia de otros métodos, podemos establecer nuestro propio `lastIndex`, para comenzar la búsqueda desde la posición dada.

For instance, let's find a word, starting from position `4`:
Por ejemplo, encontremos una palabra, comenzando desde la posición `4`:

```js run
let str = 'let varName = "value"';

let regexp = /\w+/g; // without flag "g", property lastIndex is ignored
let regexp = /\w+/g; // Sin el indicador “g”, la propiedad lastindex es ignorada.

*!*
regexp.lastIndex = 4;
Expand All @@ -87,9 +84,9 @@ let word = regexp.exec(str);
alert(word); // varName
```

We performed a search of `pattern:\w+`, starting from position `regexp.lastIndex = 4`.
Realizamos una búsqueda de `pattern:\w+`, comenzando desde la posición `regexp.lastIndex = 4`.

Please note: the search starts at position `lastIndex` and then goes further. If there's no word at position `lastIndex`, but it's somewhere after it, then it will be found:
Nota que la búsqueda comienza en la posición `lastIndex` y luego sigue adelante. Si no hay ninguna palabra en la posición `lastIndex` pero la hay en algún lugar posterior, entonces será encontrada:

```js run
let str = 'let varName = "value"';
Expand All @@ -105,26 +102,26 @@ alert(word[0]); // varName
alert(word.index); // 4
```

...So, with flag `pattern:g` property `lastIndex` sets the starting position for the search.
...Así que, con la propiedad `lastIndex` del indicador `pattern:g` se establece la posición inicial de la búsqueda.

**Flag `pattern:y` makes `regexp.exec` to look exactly at position `lastIndex`, not before, not after it.**
**El indicador `pattern:y` hace que `regexp.exec` busque exactamente en la posición `lastIndex`, ni antes ni después.**

Here's the same search with flag `pattern:y`:
Aquí está la misma búsqueda con el indicador `pattern:y`:

```js run
let str = 'let varName = "value"';

let regexp = /\w+/y;

regexp.lastIndex = 3;
alert( regexp.exec(str) ); // null (there's a space at position 3, not a word)
alert( regexp.exec(str) ); // null (Hay un espacio en la posición 3, no una palabra)

regexp.lastIndex = 4;
alert( regexp.exec(str) ); // varName (word at position 4)
alert( regexp.exec(str) ); // varName (Una palabra en la posición 4)
```

As we can see, regexp `pattern:/\w+/y` doesn't match at position `3` (unlike the flag `pattern:g`), but matches at position `4`.
Como podemos ver, el `pattern:/\w+/y` de regexp no coincide en la posición `3` (a diferencia del indicador `pattern:g`), pero coincide en la posición `4`.

Imagine, we have a long text, and there are no matches in it, at all. Then searching with flag `pattern:g` will go till the end of the text, and this will take significantly more time than the search with flag `pattern:y`.
Imagina que tenemos un texto largo, y no hay coincidencias en él. Entonces la búsqueda con el indicador `pattern:g` irá hasta el final del texto, y esto tomará significativamente más tiempo que la búsqueda con el indicador `pattern:y`.

In such tasks like lexical analysis, there are usually many searches at an exact position. Using flag `pattern:y` is the key for a good performance.
En tareas tales como el análisis léxico, normalmente hay muchas búsquedas en una posición exacta. Usar el indicador `pattern:y` es la clave para un buen desempeño.