Skip to content

Commit cddff42

Browse files
authored
Merge pull request #324 from marcellosurdi/article/regexp-lookahead-lookbehind
Lookahead and lookbehind
2 parents ffee785 + 528c5df commit cddff42

File tree

5 files changed

+78
-80
lines changed

5 files changed

+78
-80
lines changed

9-regular-expressions/14-regexp-lookahead-lookbehind/1-find-non-negative-integers/solution.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

2-
The regexp for an integer number is `pattern:\d+`.
2+
La regexp per un numero intero è `pattern:\d+`.
33

4-
We can exclude negatives by prepending it with the negative lookbehind: `pattern:(?<!-)\d+`.
4+
Possiamo escludere i numeri negativi anteponendo il segno meno con il lookbehind: `pattern:(?<!-)\d+`.
55

6-
Although, if we try it now, we may notice one more "extra" result:
6+
Anche se, nel caso in cui lo provassimo ora, potremmo notare un altro risultato inatteso:
77

88
```js run
99
let regexp = /(?<!-)\d+/g;
@@ -13,11 +13,11 @@ let str = "0 12 -5 123 -18";
1313
console.log( str.match(regexp) ); // 0, 12, 123, *!*8*/!*
1414
```
1515

16-
As you can see, it matches `match:8`, from `subject:-18`. To exclude it, we need to ensure that the regexp starts matching a number not from the middle of another (non-matching) number.
16+
Come potete osservare trova `match:8` da `subject:-18`. Per escluderlo, dobbiamo assicurarci che la regexp non cominci a cercare una corrispondenza di un numero dalla metà di un altro numero non corrispondente.
1717

18-
We can do it by specifying another negative lookbehind: `pattern:(?<!-)(?<!\d)\d+`. Now `pattern:(?<!\d)` ensures that a match does not start after another digit, just what we need.
18+
Possiamo farlo specificando un altro lookbehind negativo: `pattern:(?<!-)(?<!\d)\d+`. Ora `pattern:(?<!\d)` assicura che la corrispondenza non cominci dopo un altro numero, proprio quello che volevamo.
1919

20-
We can also join them into a single lookbehind here:
20+
Potremmo anche unire il tutto in un singolo lookbehind in questo modo:
2121

2222
```js run
2323
let regexp = /(?<![-\d])\d+/g;

9-regular-expressions/14-regexp-lookahead-lookbehind/1-find-non-negative-integers/task.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
# Find non-negative integers
1+
# Trovate gli interi non negativi
22

3-
There's a string of integer numbers.
3+
Data una stringa di numeri interi, create una regexp che cerchi solo quelli non negativi (lo zero è consentito).
44

5-
Create a regexp that looks for only non-negative ones (zero is allowed).
6-
7-
An example of use:
5+
Un esempio d'uso:
86
```js
97
let regexp = /your regexp/g;
108

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
In order to insert after the `<body>` tag, we must first find it. We can use the regular expression pattern `pattern:<body.*?>` for that.
1+
Per inserire qualcosa dopo il tag `<body>` dobbiamo prima trovarlo. A questo scopo possiamo usare l'espressione regolare `pattern:<body.*?>`.
22

3-
In this task we don't need to modify the `<body>` tag. We only need to add the text after it.
3+
In questa esercitazione non abbiamo bisogno di modificare il tag `<body>`. Dobbiamo solo aggiungere del testo dopo di esso.
44

5-
Here's how we can do it:
5+
Ecco come possiamo farlo:
66

77
```js run
88
let str = '...<body style="...">...';
@@ -11,9 +11,9 @@ str = str.replace(/<body.*?>/, '$&<h1>Hello</h1>');
1111
alert(str); // ...<body style="..."><h1>Hello</h1>...
1212
```
1313

14-
In the replacement string `$&` means the match itself, that is, the part of the source text that corresponds to `pattern:<body.*?>`. It gets replaced by itself plus `<h1>Hello</h1>`.
14+
Nella stringa di sostituzione `$&` identifica la stessa corrispondenza, in altre parole, la parte della stringa sorgente che trova riscontro con `pattern:<body.*?>`. Essa viene sostituita da se stessa più l'aggiunta di `<h1>Hello</h1>`.
1515

16-
An alternative is to use lookbehind:
16+
L'uso del lookbehind costituisce un'alternativa:
1717

1818
```js run
1919
let str = '...<body style="...">...';
@@ -22,15 +22,15 @@ str = str.replace(/(?<=<body.*?>)/, `<h1>Hello</h1>`);
2222
alert(str); // ...<body style="..."><h1>Hello</h1>...
2323
```
2424

25-
As you can see, there's only lookbehind part in this regexp.
25+
Come potete osservare, c'è solo la parte di lookbehind in questa regexp.
2626

27-
It works like this:
28-
- At every position in the text.
29-
- Check if it's preceeded by `pattern:<body.*?>`.
30-
- If it's so then we have the match.
27+
Funziona in questo modo:
28+
- Per ogni posizione nella stringa.
29+
- Verifica se è preceduta da `pattern:<body.*?>`.
30+
- In caso affermativo abbiamo trovato la corrispondenza.
3131

32-
The tag `pattern:<body.*?>` won't be returned. The result of this regexp is literally an empty string, but it matches only at positions preceeded by `pattern:<body.*?>`.
32+
Il tag `pattern:<body.*?>` non verrà restituito. Il risultato di questa regexp è letteralmente una stringa vuota, ma individua le posizioni precedute da `pattern:<body.*?>`.
3333

34-
So it replaces the "empty line", preceeded by `pattern:<body.*?>`, with `<h1>Hello</h1>`. That's the insertion after `<body>`.
34+
Quindi sostituisce uno "spazio vuoto" preceduto da `pattern:<body.*?>`, con `<h1>Hello</h1>`. In altre parole effettua un inserimento dopo `<body>`.
3535

36-
P.S. Regexp flags, such as `pattern:s` and `pattern:i` can also be useful: `pattern:/<body.*?>/si`. The `pattern:s` flag makes the dot `pattern:.` match a newline character, and `pattern:i` flag makes `pattern:<body>` also match `match:<BODY>` case-insensitively.
36+
P.S. I flag `pattern:s` e `pattern:i` potrebbero inoltre risultare utili: `pattern:/<body.*?>/si`. Il flag `pattern:s` fa in modo che il `pattern:.` identifichi anche un carattere di nuova riga, e con il flag `pattern:i` otteniamo che `pattern:<body>` e `match:<BODY>` costituiscano entrambi un riscontro.

9-regular-expressions/14-regexp-lookahead-lookbehind/2-insert-after-head/task.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# Insert After Head
1+
# Inserimento dopo la sezione head
22

3-
We have a string with an HTML Document.
3+
Abbiamo una stringa e un documento HTML.
44

5-
Write a regular expression that inserts `<h1>Hello</h1>` immediately after `<body>` tag. The tag may have attributes.
5+
Scrivete un'espressione regolare che inserisca `<h1>Hello</h1>` subito dopo il tag `<body>`. Il tag può avere degli attributi.
66

7-
For instance:
7+
Per esempio:
88

99
```js
1010
let regexp = /your regular expression/;
@@ -20,7 +20,7 @@ let str = `
2020
str = str.replace(regexp, `<h1>Hello</h1>`);
2121
```
2222

23-
After that the value of `str` should be:
23+
Dopo l'inserimento il valore di `str` dovrebbe essere:
2424
```html
2525
<html>
2626
<body style="height: 200px"><h1>Hello</h1>
Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,107 @@
1-
# Lookahead and lookbehind
1+
# Lookahead e lookbehind
22

3-
Sometimes we need to find only those matches for a pattern that are followed or preceded by another pattern.
3+
Talvolta abbiamo bisogno di trovare soltanto quei riscontri per un pattern che sono seguiti o preceduti da un altro pattern.
44

5-
There's a special syntax for that, called "lookahead" and "lookbehind", together referred to as "lookaround".
5+
Esiste a questo scopo una sintassi speciale denominata "lookahead" e "lookbehind", indicata complessivamente con il termine "lookaround".
66

7-
For the start, let's find the price from the string like `subject:1 turkey costs 30€`. That is: a number, followed by `subject:€` sign.
7+
Per cominciare troviamo il prezzo in una stringa come `subject:1 turkey costs 30€`. In parole semplici: un numero seguito dal simbolo di valuta `subject:€`.
88

99
## Lookahead
1010

11-
The syntax is: `pattern:X(?=Y)`, it means "look for `pattern:X`, but match only if followed by `pattern:Y`". There may be any pattern instead of `pattern:X` and `pattern:Y`.
11+
La sintassi è: `pattern:X(?=Y)`, che significa "cerca `pattern:X`, ma trova la corrispondenza solo se seguita da `pattern:Y`". Possiamo sostituire `pattern:X` e `pattern:Y` con un pattern qualsiasi.
1212

13-
For an integer number followed by `subject:€`, the regexp will be `pattern:\d+(?=€)`:
13+
Per un numero intero seguito da `subject:€`, la regexp sarà `pattern:\d+(?=€)`:
1414

1515
```js run
1616
let str = "1 turkey costs 30€";
1717

18-
alert( str.match(/\d+(?=€)/) ); // 30, the number 1 is ignored, as it's not followed by
18+
alert( str.match(/\d+(?=€)/) ); // 30, viene ignorato il numero 1 in quanto non seguito da
1919
```
2020

21-
Please note: the lookahead is merely a test, the contents of the parentheses `pattern:(?=...)` is not included in the result `match:30`.
21+
Si noti che la parte lookahead è solo un test e pertanto il contenuto tra parentesi `pattern:(?=...)` non è incluso nel risultato `match:30`.
2222

23-
When we look for `pattern:X(?=Y)`, the regular expression engine finds `pattern:X` and then checks if there's `pattern:Y` immediately after it. If it's not so, then the potential match is skipped, and the search continues.
23+
Quando cerchiamo `pattern:X(?=Y)` l'interprete dell'espressione regolare trova `pattern:X` e successivamente verifica anche la presenza di `pattern:Y` subito dopo di esso. In caso contrario la corrispondenza potenziale viene scartata e la ricerca prosegue.
2424

25-
More complex tests are possible, e.g. `pattern:X(?=Y)(?=Z)` means:
25+
Sono possibili test più complessi, ad esempio `pattern:X(?=Y)(?=Z)` significa:
2626

27-
1. Find `pattern:X`.
28-
2. Check if `pattern:Y` is immediately after `pattern:X` (skip if isn't).
29-
3. Check if `pattern:Z` is also immediately after `pattern:X` (skip if isn't).
30-
4. If both tests passed, then the `pattern:X` is a match, otherwise continue searching.
27+
1. Trova `pattern:X`.
28+
2. Verifica se `pattern:Y` sia subito dopo `pattern:X` (non proseguire in caso contrario).
29+
3. Verifica se `pattern:Z` sia anch'esso dopo `pattern:X` (non proseguire in caso contrario).
30+
4. Se entrambi i test trovano riscontro considera `pattern:X` una corrispondenza, diversamente continua la ricerca.
3131

32-
In other words, such pattern means that we're looking for `pattern:X` followed by `pattern:Y` and `pattern:Z` at the same time.
32+
In altre parole, questo pattern significa che stiamo cercando `pattern:X` seguito sia da `pattern:Y` sia da `pattern:Z`.
3333

34-
That's only possible if patterns `pattern:Y` and `pattern:Z` aren't mutually exclusive.
34+
Il che è possibile solo se i pattern `pattern:Y` e `pattern:Z` non si escludono a vicenda.
3535

36-
For example, `pattern:\d+(?=\s)(?=.*30)` looks for `pattern:\d+` that is followed by a space `pattern:(?=\s)`, and there's `30` somewhere after it `pattern:(?=.*30)`:
36+
Per esempio, `pattern:\d+(?=\s)(?=.*30)` cerca `pattern:\d+` seguito da uno spazio `pattern:(?=\s)`, e poi c'è `30` da qualche parte dopo di esso `pattern:(?=.*30)`:
3737

3838
```js run
3939
let str = "1 turkey costs 30€";
4040

4141
alert( str.match(/\d+(?=\s)(?=.*30)/) ); // 1
4242
```
4343

44-
In our string that exactly matches the number `1`.
44+
Nella nostra stringa trova esatta corrispondenza nel numero `1`.
4545

46-
## Negative lookahead
46+
## Lookahead negativo
4747

48-
Let's say that we want a quantity instead, not a price from the same string. That's a number `pattern:\d+`, NOT followed by `subject:€`.
48+
Supponiamo invece di volere nella stessa stringa solo la quantità, non il prezzo. Quindi il numero `pattern:\d+`, NON seguito da `subject:€`.
4949

50-
For that, a negative lookahead can be applied.
50+
A questo scopo può essere applicato un lookahead negativo.
5151

52-
The syntax is: `pattern:X(?!Y)`, it means "search `pattern:X`, but only if not followed by `pattern:Y`".
52+
La sintassi è: `pattern:X(?!Y)`, significa "cerca `pattern:X`, ma solo se non seguito da `pattern:Y`".
5353

5454
```js run
5555
let str = "2 turkeys cost 60€";
5656

57-
alert( str.match(/\d+\b(?!€)/g) ); // 2 (the price is not matched)
57+
alert( str.match(/\d+\b(?!€)/g) ); // 2 (il prezzo non costituisce corrispondenza)
5858
```
5959

6060
## Lookbehind
6161

62-
Lookahead allows to add a condition for "what follows".
62+
Lookahead permette di porre una condizione per "quello che segue".
6363

64-
Lookbehind is similar, but it looks behind. That is, it allows to match a pattern only if there's something before it.
64+
Lookbehind è simile, ma cerca quello che precede. Consente quindi di trovare una corrispondenza per un pattern solo se c'è qualcosa prima di esso.
6565

66-
The syntax is:
67-
- Positive lookbehind: `pattern:(?<=Y)X`, matches `pattern:X`, but only if there's `pattern:Y` before it.
68-
- Negative lookbehind: `pattern:(?<!Y)X`, matches `pattern:X`, but only if there's no `pattern:Y` before it.
66+
La sintassi è:
67+
- Lookbehind positivo: `pattern:(?<=Y)X`, trova `pattern:X`, ma solo se c'è `pattern:Y` prima di esso.
68+
- Lookbehind negativo: `pattern:(?<!Y)X`, trova `pattern:X`, ma solo se non c'è alcun `pattern:Y` prima di esso.
6969

70-
For example, let's change the price to US dollars. The dollar sign is usually before the number, so to look for `$30` we'll use `pattern:(?<=\$)\d+` -- an amount preceded by `subject:$`:
70+
Cambiamo, ad esempio, il prezzo in dollari USA. Il segno del dollaro è posto di solito prima del numero, per cercare pertanto `$30` useremo `pattern:(?<=\$)\d+` un importo preceduto da `subject:$`:
7171

7272
```js run
7373
let str = "1 turkey costs $30";
7474

75-
// the dollar sign is escaped \$
76-
alert( str.match(/(?<=\$)\d+/) ); // 30 (skipped the sole number)
75+
// facciamo l'escape al segno del dollaro \$
76+
alert( str.match(/(?<=\$)\d+/) ); // 30 (salta il numero senza segno di valuta)
7777
```
7878

79-
And, if we need the quantity -- a number, not preceded by `subject:$`, then we can use a negative lookbehind `pattern:(?<!\$)\d+`:
79+
Se abbiamo bisogno della quantità, il numero, non preceduto da `subject:$`, allora possiamo usare il lookbehind negativo `pattern:(?<!\$)\d+`:
8080

8181
```js run
8282
let str = "2 turkeys cost $60";
8383

84-
alert( str.match(/(?<!\$)\b\d+/g) ); // 2 (the price is not matched)
84+
alert( str.match(/(?<!\$)\b\d+/g) ); // 2 (il risultato non include il prezzo)
8585
```
8686

87-
## Capturing groups
87+
## Gruppi di acquisizione
8888

89-
Generally, the contents inside lookaround parentheses does not become a part of the result.
89+
Generalmente il contenuto dentro le parentesi di lookaround non diventa parte del risultato.
9090

91-
E.g. in the pattern `pattern:\d+(?=€)`, the `pattern:€` sign doesn't get captured as a part of the match. That's natural: we look for a number `pattern:\d+`, while `pattern:(?=€)` is just a test that it should be followed by `subject:€`.
91+
Nel pattern `pattern:\d+(?=€)`, ad esempio, il segno `pattern:€` non viene acquisito nella corrispondenza. È del tutto normale: stiamo cercando il numero `pattern:\d+`, mentre `pattern:(?=€)` è solo un test che indica che il numero dovrebbe essere seguito da `subject:€`.
9292

93-
But in some situations we might want to capture the lookaround expression as well, or a part of it. That's possible. Just wrap that part into additional parentheses.
93+
In alcune situazioni, tuttavia, potremmo voler catturare anche l'espressione del lookaround, o una parte di essa. Questo è possibile: è sufficiente racchiudere la parte desiderata all'interno di parentesi aggiuntive.
9494

95-
In the example below the currency sign `pattern:(€|kr)` is captured, along with the amount:
95+
Nell'esempio sotto, il segno di valuta `pattern:(€|kr)` viene acquisito insieme all'importo:
9696

9797
```js run
9898
let str = "1 turkey costs 30€";
99-
let regexp = /\d+(?=(€|kr))/; // extra parentheses around €|kr
99+
let regexp = /\d+(?=(€|kr))/; // parentesi addizionali intorno €|kr
100100

101101
alert( str.match(regexp) ); // 30, €
102102
```
103103

104-
And here's the same for lookbehind:
104+
Stesso discorso per il lookbehind:
105105

106106
```js run
107107
let str = "1 turkey costs $30";
@@ -110,21 +110,21 @@ let regexp = /(?<=(\$|£))\d+/;
110110
alert( str.match(regexp) ); // 30, $
111111
```
112112

113-
## Summary
113+
## Riepilogo
114114

115-
Lookahead and lookbehind (commonly referred to as "lookaround") are useful when we'd like to match something depending on the context before/after it.
115+
Il lookahead e il lookbehind (comunemente denominati con il termine "lookaround") sono utili quando vogliamo trovare qualcosa in base a ciò viene prima o dopo di esso.
116116

117-
For simple regexps we can do the similar thing manually. That is: match everything, in any context, and then filter by context in the loop.
117+
Nel caso di espressioni regolari semplici potremmo ottenere lo stesso risultato manualmente. In altre parole: troviamo ogni riscontro, e quindi filtriamo i risultati in base alla posizione nel ciclo iterativo.
118118

119-
Remember, `str.match` (without flag `pattern:g`) and `str.matchAll` (always) return matches as arrays with `index` property, so we know where exactly in the text it is, and can check the context.
119+
Ricordiamoci che `str.match` (senza il flag `pattern:g`) e `str.matchAll` (sempre) restituiscono i risultati in un array con la proprietà `index`, conosciamo pertanto l'esatta posizione della corrispondenza e possiamo stabilirne il contesto.
120120

121-
But generally lookaround is more convenient.
121+
Generalmente, però, il lookaround è più efficiente.
122122

123-
Lookaround types:
123+
Tipi di lookaround:
124124

125-
| Pattern | type | matches |
125+
| Pattern | Tipo | Riscontri |
126126
|--------------------|------------------|---------|
127-
| `X(?=Y)` | Positive lookahead | `pattern:X` if followed by `pattern:Y` |
128-
| `X(?!Y)` | Negative lookahead | `pattern:X` if not followed by `pattern:Y` |
129-
| `(?<=Y)X` | Positive lookbehind | `pattern:X` if after `pattern:Y` |
130-
| `(?<!Y)X` | Negative lookbehind | `pattern:X` if not after `pattern:Y` |
127+
| `X(?=Y)` | Lookahead positivo | `pattern:X` se seguito da `pattern:Y` |
128+
| `X(?!Y)` | Lookahead negativo | `pattern:X` se seguito da `pattern:Y` |
129+
| `(?<=Y)X` | Lookbehind positivo | `pattern:X` se dopo `pattern:Y` |
130+
| `(?<!Y)X` | Lookbehind negativo | `pattern:X` se dopo `pattern:Y` |

0 commit comments

Comments
 (0)