Bonjour,

J'ai étudié les constructions suivantes :

  • positive look behind
  • positive look ahead
  • negative look behind
  • negative look ahead


D'après ce que j'ai compris, ces constructions désignent un caractère en fonction d'une condition :

  • positive look behind: désigne un caractère à condition que ce dernier soit précédé par un caractère donné.
  • positive look ahead: désigne un caractère à condition que ce dernier soit suivi par un caractère donné.
  • negative look behind: désigne un caractère à condition que ce dernier ne soit pas précédé par un caractère donné.
  • negative look ahead: désigne un caractère à condition que ce dernier ne soit pas suivi par un caractère donné.


Sauf que la construction "positive look ahead" ne désigne pas un caractère, mais deux.

Illustration en Python :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from typing import Optional, Pattern, Match
import re
 
print("Positive look-ahead: a(?:b) ('a' followed by 'b')")
p: Pattern = re.compile('a(?:b)')
text: str = 'abc'
m: Optional[Match] = p.search(text)
print(f'{text} => {m.group(0)}')  # => ab
print('')
 
# Negative look-ahead: "a" is not followed by "b".
 
print("Negative look-ahead: a(?!b) ('a' not followed by 'b')")
p: Pattern = re.compile('a(?!b)')
text: str = 'ax'
m: Optional[Match] = p.match(text)
print(f'{text} => {m.group(0)}')  # => a
print('')
 
# Negative look-behind: "b" is not preceded by "a".
 
print("Negative look-behind: (?<!a)b ('b' not preceded by 'a')")
p: Pattern = re.compile('(?<!a)b')
text: str = 'xb'
m: Optional[Match] = p.search(text)
print(f'{text} => {m.group(0)}')  # => b
print('')
 
# Positive look-behind: "b" is preceded by "a".
 
print("Positive look-behind: (?<=a)b ('b' preceded by 'a')")
p: Pattern = re.compile('(?<=a)b')
text: str = 'ab'
m: Optional[Match] = p.search(text)
print(f'{text} => {m.group(0)}')  # => b
print('')
Le résultat :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
Positive look-ahead: a(?:b) ('a' followed by 'b')
abc => ab
 
Negative look-ahead: a(?!b) ('a' not followed by 'b')
ax => a
 
Negative look-behind: (?<!a)b ('b' not preceded by 'a')
xb => b
 
Positive look-behind: (?<=a)b ('b' preceded by 'a')
ab => b
Le m'attendais à ce que "a(?:b)" retourne "a" et non "ab".

Quelqu'un pourrait-il m'expliquer la logique derrière ce résultat ?

Merci.



Ajout

L'utilisation de Perl retourne les mêmes résultats :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use strict;
 
if ('ab' =~ m/a(?:b)/) {
	print("${&}\n")  # => ab
}
 
if ('ax' =~ m/a(?!b)/) {
	print("${&}\n")  # => a
}
 
if ('xb' =~ m/(?<!a)b/) {
	print("${&}\n")  # => b
}
 
if ('ab' =~ m/(?<=a)b/) {
	print("${&}\n")  # => b
}