Skip to content

Commit 3a0af57

Browse files
committed
Update 9-regular-expressions\10-regexp-greedy-and-lazy\article.md
1 parent f662d64 commit 3a0af57

File tree

1 file changed

+56
-56
lines changed
  • 9-regular-expressions/10-regexp-greedy-and-lazy

1 file changed

+56
-56
lines changed

9-regular-expressions/10-regexp-greedy-and-lazy/article.md

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Prendiamo ad esempio la seguente esercitazione.
88

99
Abbiamo bisogno di rimpiazzare tutti i doppi apici `"..."` in un testo con le virgolette basse: `«...»`, che sono preferite nella tipografia di molti paesi.
1010

11-
Ad esempio: `"Hello, world"` dovrebbe diventare `«Hello, world»`. Esistono altre virgolette, come `„Witam, świat!”` (in Polonia) o `「你好,世界」` (in Cina), in questo caso, tuttavia, scegliamo `«...»`.
11+
Ad esempio: `"Hello, world"` dovrebbe diventare `«Hello, world»`. Esistono altre virgolette, come `„Witam, świat!”` in Polonia o `「你好,世界」` in Cina, in questo caso, tuttavia, scegliamo `«...»`.
1212

1313
Innanzitutto dobbiamo individuare le stringhe tra doppi apici per poi sostituirli.
1414

@@ -24,15 +24,15 @@ let str = 'a "witch" and her "broom" is one';
2424
alert( str.match(regexp) ); // "witch" and her "broom"
2525
```
2626

27-
...Non funziona come desideravamo!
27+
Non funziona come desideravamo!
2828

2929
Invece di trovare i due riscontri `match:"witch"` e `match:"broom"`, ne trova solo uno: `match:"witch" and her "broom"`.
3030

3131
Questo fenomeno può essere descritto così: "l'avidità è la causa di tutti i mali".
3232

3333
## La ricerca in modalità greedy (avida)
3434

35-
Per trovare un riscontro, il motore dell'espressione regolare usa il seguente algoritmo:
35+
Per trovare un riscontro, l'interprete dell'espressione regolare usa il seguente algoritmo:
3636

3737
- Per ogni posizione nella stringa
3838
- Prova a trovare un riscontro del pattern in quella posizione.
@@ -42,27 +42,27 @@ Questa procedura generica non ci spiega con evidenza perché l'espressione regol
4242

4343
1. Il primo carattere del pattern è un doppio apice `pattern:"`.
4444

45-
Il motore dell'espressione regolare prova a trovarlo nella posizione zero della stringa `subject:a "witch" and her "broom" is one`, ma in quel punto trova `subject:a`, pertanto non c'è immediata corrispondenza.
45+
L'interprete dell'espressione regolare prova a trovarlo nella posizione zero della stringa `subject:a "witch" and her "broom" is one`, ma in quel punto trova `subject:a`, pertanto non c'è immediata corrispondenza.
4646

4747
Quindi procede: passa alle successive posizioni nella stringa sorgente e prova a trovare lì il primo carattere del pattern, prima fallisce nuovamente, e poi trova finalmente il doppio apice nella terza posizione:
4848

4949
![](witch_greedy1.svg)
5050

51-
2. Rilevato il doppio apice, il motore tenta di trovare riscontro per il resto del pattern. Verifica se il resto della stringa sia conforme a `pattern:.+"`.
51+
2. Rilevato il doppio apice, tenta di trovare riscontro per il resto del pattern. Verifica se il resto della stringa sia conforme a `pattern:.+"`.
5252

5353
Nel nostro esempio il successivo carattere del pattern è `pattern:.` (un punto) che indica "qualsiasi carattere tranne una nuova riga". Trova pertanto corrispondenza nel carattere successivo della stringa `match:'w'`:
5454

5555
![](witch_greedy2.svg)
5656

57-
3. Successivamente il punto trova ulteriori riscontri per via del quantificatore `pattern:.+`. Il motore dell'espressione regolare aggiunge un carattere dopo l'altro.
57+
3. Successivamente il punto trova ulteriori riscontri per via del quantificatore `pattern:.+`. L'interprete dell'espressione regolare aggiunge un carattere dopo l'altro.
5858

59-
...Fino a quando? Tutti i caratteri corrispondono al punto, quindi si ferma solo quando raggiunge la fine della stringa:
59+
Fino a quando? Tutti i caratteri corrispondono al punto, quindi si ferma solo quando raggiunge la fine della stringa:
6060

6161
![](witch_greedy3.svg)
6262

63-
4. A questo punto il motore cessa di ripetere `pattern:.+` e prova a trovare il prossimo carattere del pattern. Si tratta del doppio apice `pattern:"`. C'è un problema però: la stringa è finita, non ci sono più caratteri!
63+
4. A questo punto cessa di ripetere `pattern:.+` e prova a trovare il prossimo carattere del pattern. Si tratta del doppio apice `pattern:"`. C'è un problema però: la stringa è finita, non ci sono più caratteri!
6464

65-
Il motore dell'espressione regolare capisce di aver preso troppi caratteri per `pattern:.+` e comincia a *retrocedere*.
65+
L'interprete dell'espressione regolare capisce di aver preso troppi caratteri per `pattern:.+` e comincia a *retrocedere*.
6666

6767
In altre parole accorcia di un carattere la corrispondenza per il quantificatore:
6868

@@ -72,13 +72,13 @@ Questa procedura generica non ci spiega con evidenza perché l'espressione regol
7272

7373
Se ci fosse stato un doppio apice, la ricerca sarebbe terminata, ma l'ultima carattere è una `subject:'e'`, nessun riscontro quindi.
7474

75-
5. ...Allora il motore diminuisce di un ulteriore carattere il numero delle ripetizioni di `pattern:.+`:
75+
5. Allora l'interprete diminuisce di un ulteriore carattere il numero delle ripetizioni di `pattern:.+`:
7676

7777
![](witch_greedy5.svg)
7878

7979
Anche il carattere `subject:'n'` non soddisfa la ricerca di `pattern:'"'`.
8080

81-
6. Il motore continua a retrocedere: diminuisce le ripetizioni per `pattern:'.'` finché il resto del pattern (nel nostro caso `pattern:'"'`) non trova riscontro:
81+
6. L'interprete continua a retrocedere: diminuisce le ripetizioni per `pattern:'.'` finché il resto del pattern (nel nostro caso `pattern:'"'`) non trova riscontro:
8282

8383
![](witch_greedy6.svg)
8484

@@ -90,7 +90,7 @@ Probabilmente non è quello che ci aspettavamo, ma funziona così.
9090

9191
**In modalità greedy (quella predefinita) un quantificatore viene ripetuto quante più volte possibile.**
9292

93-
Il motore della regexp aggiunge quanti più caratteri possibili alla corrispondenza con `pattern:.+`, successivamente retrocede di un carattere alla volta se il resto del pattern non trova riscontro.
93+
L'interprete della regexp aggiunge quanti più caratteri possibili alla corrispondenza con `pattern:.+`, successivamente retrocede di un carattere alla volta se il resto del pattern non trova riscontro.
9494

9595
L'obiettivo della nostra esercitazione non è questo, proprio in questi casi viene in soccorso la modalità lazy.
9696

@@ -118,16 +118,16 @@ Per comprendere distintamente cosa sia cambiato, seguiamo la ricerca passo dopo
118118

119119
![](witch_greedy1.svg)
120120

121-
2. Anche il secondo step è simile: il motore trova una corrispondenza per il punto `pattern:'.'`:
121+
2. Anche il secondo step è simile: l'interprete trova una corrispondenza per il punto `pattern:'.'`:
122122

123123
![](witch_greedy2.svg)
124124

125-
3. Da questo punto la ricerca procede in modo differente. Dal momento che il quantificatore è in modalità lazy `pattern:+?`, il motore non prova a cercare il punto più di una volta, si ferma e cerca subito la corrispondenza con il resto del pattern `pattern:'"'`:
125+
3. Da questo punto la ricerca procede in modo differente. Dal momento che il quantificatore è in modalità lazy `pattern:+?`, l'interprete non prova a cercare il punto più di una volta, si ferma e cerca subito la corrispondenza con il resto del pattern `pattern:'"'`:
126126

127127
![](witch_lazy3.svg)
128128

129129
Se ci fosse un doppio apice a questo punto la ricerca sarebbe già terminata, ma c'è una `'i'` e quindi nessuna corrispondenza.
130-
4. Il motore della regexp allora aumenta il numero delle ripetizioni per il punto e riprova:
130+
4. L'interprete della regexp allora aumenta il numero delle ripetizioni per il punto e riprova:
131131

132132
![](witch_lazy4.svg)
133133

@@ -140,7 +140,7 @@ Per comprendere distintamente cosa sia cambiato, seguiamo la ricerca passo dopo
140140

141141
![](witch_lazy6.svg)
142142

143-
In questo esempio abbiamo visto come funziona la modalità lazy per `pattern:+?`. I quantificatori `pattern:*?` e `pattern:??` operano in modo simile: il motore della regexp aumenta il numero delle ripetizioni solo se il resto del pattern non ha corrispondenza in una data posizione.
143+
In questo esempio abbiamo visto come funziona la modalità lazy per `pattern:+?`. I quantificatori `pattern:*?` e `pattern:??` operano in modo simile: aumentano il numero delle ripetizioni solo se il resto del pattern non ha corrispondenza in una data posizione.
144144

145145
**La modalità lazy è abilitata unicamente per il quantificatore seguito da `?`.**
146146

@@ -156,7 +156,7 @@ alert( "123 456".match(/\d+ \d+?/) ); // 123 4
156156
2. Segue la corrispondenza dello spazio nel pattern.
157157
3. A questo punto c'è `pattern:\d+?`. Il quantificatore è modalità lazy, perciò trova solo una cifra `match:4` e prova a verificare se il resto del pattern è soddisfatto.
158158

159-
...Nel pattern, tuttavia, non c'è niente dopo `pattern:\d+?`.
159+
Nel pattern, tuttavia, non c'è niente dopo `pattern:\d+?`.
160160

161161
La modalità lazy non ripete nulla se non c'è un motivo. Il pattern è finito e conclude la ricerca. La nostra corrispondenza è `match:123 4`.
162162

@@ -168,11 +168,11 @@ Ma per comprendere come funzionino le espressioni regolari e come implementarle
168168
Del resto è difficile ottimizzare le espressioni regolari complesse, pertanto la ricerca potrebbe anche funzionare esattamente come indicato.
169169
```
170170

171-
## Approccio alternativo
171+
## Un approccio alternativo
172172

173-
With regexps, there's often more than one way to do the same thing.
173+
Con le espressioni regolari, spesso c'è più di un modo di ottenere lo stesso risultato.
174174

175-
In our case we can find quoted strings without lazy mode using the regexp `pattern:"[^"]+"`:
175+
Nel nostro caso potremmo trovare le stringhe tra doppi apici senza la modalità lazy, usando la regexp `pattern:"[^"]+"`:
176176

177177
```js run
178178
let regexp = /"[^"]+"/g;
@@ -182,120 +182,120 @@ let str = 'a "witch" and her "broom" is one';
182182
alert( str.match(regexp) ); // "witch", "broom"
183183
```
184184

185-
The regexp `pattern:"[^"]+"` gives correct results, because it looks for a quote `pattern:'"'` followed by one or more non-quotes `pattern:[^"]`, and then the closing quote.
185+
La regexp `pattern:"[^"]+"` dà il risultato corretto, perché cerca un doppio apice `pattern:'"'`, seguito da uno o più caratteri che non siano doppi apici `pattern:[^"]` e successivamente un doppio apice di chiusura.
186186

187-
When the regexp engine looks for `pattern:[^"]+` it stops the repetitions when it meets the closing quote, and we're done.
187+
Quando l'interprete della regexp cerca `pattern:[^"]+` si arresta quando incontra il doppio apice di chiusura e termina il suo lavoro.
188188

189-
Please note, that this logic does not replace lazy quantifiers!
189+
Si noti che questa logica non rimpiazza i quantificatori lazy!
190190

191-
It is just different. There are times when we need one or another.
191+
Sono due approcci differenti. Talvolta ci serve uno, a volte l'altro.
192192

193-
**Let's see an example where lazy quantifiers fail and this variant works right.**
193+
**Guardiamo un esempio in cui i quantificatori lazy falliscono e questa variante funziona a dovere.**
194194

195-
For instance, we want to find links of the form `<a href="..." class="doc">`, with any `href`.
195+
Se volessimo, per esempio, trovare dei link di questo tipo `<a href="..." class="doc">`, con qualsiasi contenuto per `href`.
196196

197-
Which regular expression to use?
197+
Quale espressione regolare dovremmo usare?
198198

199-
The first idea might be: `pattern:/<a href=".*" class="doc">/g`.
199+
La prima idea potrebbe essere: `pattern:/<a href=".*" class="doc">/g`.
200200

201-
Let's check it:
201+
Proviamo:
202202
```js run
203203
let str = '...<a href="link" class="doc">...';
204204
let regexp = /<a href=".*" class="doc">/g;
205205

206-
// Works!
206+
// Funziona!
207207
alert( str.match(regexp) ); // <a href="link" class="doc">
208208
```
209209

210-
It worked. But let's see what happens if there are many links in the text?
210+
Ha funzionato. Ma vediamo, cosa succede se ci sono più link nel testo?
211211

212212
```js run
213213
let str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
214214
let regexp = /<a href=".*" class="doc">/g;
215215

216-
// Whoops! Two links in one match!
216+
// Ops! Due link in una sola corrispondenza!
217217
alert( str.match(regexp) ); // <a href="link1" class="doc">... <a href="link2" class="doc">
218218
```
219219

220-
Now the result is wrong for the same reason as our "witches" example. The quantifier `pattern:.*` took too many characters.
220+
Il risultato adesso è errato per lo stesso motivo dell'esempio di prima con "witches". Il quantificatore `pattern:.*` ha preso troppi caratteri.
221221

222-
The match looks like this:
222+
Possiamo spiegare la corrispondenza in questo modo:
223223

224224
```html
225225
<a href="....................................." class="doc">
226226
<a href="link1" class="doc">... <a href="link2" class="doc">
227227
```
228228

229-
Let's modify the pattern by making the quantifier `pattern:.*?` lazy:
229+
Modifichiamo allora il pattern rendendo lazy il quantificatore `pattern:.*?`:
230230

231231
```js run
232232
let str = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
233233
let regexp = /<a href=".*?" class="doc">/g;
234234

235-
// Works!
235+
// Funziona!
236236
alert( str.match(regexp) ); // <a href="link1" class="doc">, <a href="link2" class="doc">
237237
```
238238

239-
Now it seems to work, there are two matches:
239+
Ora sembra sembra funzionare, ci sono due riscontri:
240240

241241
```html
242242
<a href="....." class="doc"> <a href="....." class="doc">
243243
<a href="link1" class="doc">... <a href="link2" class="doc">
244244
```
245245

246-
...But let's test it on one more text input:
246+
Ma proviamo ancora su un altro testo:
247247

248248
```js run
249249
let str = '...<a href="link1" class="wrong">... <p style="" class="doc">...';
250250
let regexp = /<a href=".*?" class="doc">/g;
251251

252-
// Wrong match!
252+
// Corrispondenza errata!
253253
alert( str.match(regexp) ); // <a href="link1" class="wrong">... <p style="" class="doc">
254254
```
255255

256-
Now it fails. The match includes not just a link, but also a lot of text after it, including `<p...>`.
256+
Ora fallisce. La corrispondenza include non solo il link, ma anche molto altro testo dopo di esso, incluso `<p...>`.
257257

258-
Why?
258+
Perché?
259259

260-
That's what's going on:
260+
Ecco quello che sta succedendo:
261261

262-
1. First the regexp finds a link start `match:<a href="`.
263-
2. Then it looks for `pattern:.*?`: takes one character (lazily!), check if there's a match for `pattern:" class="doc">` (none).
264-
3. Then takes another character into `pattern:.*?`, and so on... until it finally reaches `match:" class="doc">`.
262+
1. Per prima cosa la regexp trova la prima parte del link `match:<a href="`.
263+
2. Dopo cerca `pattern:.*?`: considera un solo carattere (in modalità lazy!), verifica se c'è riscontro con `pattern:" class="doc">` (nessuna).
264+
3. Successivamente prende un altro carattere per `pattern:.*?`, e così via...fino al raggiungimento di `match:" class="doc">`.
265265

266-
But the problem is: that's already beyond the link `<a...>`, in another tag `<p>`. Not what we want.
266+
Ma il problema è: quella parte è già al di fuori del link `<a...>`, in un altro tag `<p>`. Non è quello che desideriamo.
267267

268-
Here's the picture of the match aligned with the text:
268+
Ecco la rappresentazione della corrispondenza con il testo allineato:
269269

270270
```html
271271
<a href="..................................." class="doc">
272272
<a href="link1" class="wrong">... <p style="" class="doc">
273273
```
274274

275-
So, we need the pattern to look for `<a href="...something..." class="doc">`, but both greedy and lazy variants have problems.
275+
Ricapitoliamo, abbiamo bisogno del pattern per cercare `<a href="...something..." class="doc">`, ma entrambe le varianti greedy e lazy danno problemi.
276276

277-
The correct variant can be: `pattern:href="[^"]*"`. It will take all characters inside the `href` attribute till the nearest quote, just what we need.
277+
Un'alternativa corretta potrebbe essere: `pattern:href="[^"]*"`. Essa prenderà tutti i caratteri dentro l'attributo `href` fino al doppio apice più vicino. Proprio quello di cui abbiamo bisogno!
278278

279-
A working example:
279+
Ecco un esempio funzionante:
280280

281281
```js run
282282
let str1 = '...<a href="link1" class="wrong">... <p style="" class="doc">...';
283283
let str2 = '...<a href="link1" class="doc">... <a href="link2" class="doc">...';
284284
let regexp = /<a href="[^"]*" class="doc">/g;
285285

286-
// Works!
287-
alert( str1.match(regexp) ); // null, no matches, that's correct
286+
// Funziona!
287+
alert( str1.match(regexp) ); // null, è corretto che non ci sia alcun riscontro
288288
alert( str2.match(regexp) ); // <a href="link1" class="doc">, <a href="link2" class="doc">
289289
```
290290

291291
## Riepilogo
292292

293-
Quantifiers have two modes of work:
293+
I quantificatori possono funzionare in due modalità differenti:
294294

295295
Greedy
296-
: By default the regular expression engine tries to repeat the quantified character as many times as possible. For instance, `pattern:\d+` consumes all possible digits. When it becomes impossible to consume more (no more digits or string end), then it continues to match the rest of the pattern. If there's no match then it decreases the number of repetitions (backtracks) and tries again.
296+
: L'interprete delle espressioni regolari, in via predefinita, prova a ripetere un quantificatore quante più volte possibile. Per esempio, `pattern:\d+` considera tutte le cifre disponibili. Quando diventa impossibile trovarne ancora (non ci sono più cifre o è finita la stringa), allora continua a cercare la corrispondenza con il resto del pattern. Se non trova riscontro allora retrocede, diminuisce il numero di ripetizioni e prova ancora.
297297

298298
Lazy
299-
: Enabled by the question mark `pattern:?` after the quantifier. The regexp engine tries to match the rest of the pattern before each repetition of the quantified character.
299+
: Abilitata dal punto interrogativo `pattern:?` dopo il quantificatore. L'interprete delle regexp prova la corrispondenza del resto del pattern prima di ogni ripetizione di un carattere quantificato.
300300

301-
As we've seen, the lazy mode is not a "panacea" from the greedy search. An alternative is a "fine-tuned" greedy search, with exclusions, as in the pattern `pattern:"[^"]+"`.
301+
Come abbiamo visto, la modalità lazy non è una "panacea" per i problemi della ricerca greedy. Un'alternativa può essere una ricerca greedy "calibrata", avvalendoci di esclusioni come nel pattern `pattern:"[^"]+"`.

0 commit comments

Comments
 (0)