]> git.proxmox.com Git - pve-eslint.git/blob - eslint/docs/rules/no-useless-backreference.md
bump version to 8.4.0-3
[pve-eslint.git] / eslint / docs / rules / no-useless-backreference.md
1 # Disallow useless backreferences in regular expressions (no-useless-backreference)
2
3 In JavaScript regular expressions, it's syntactically valid to define a backreference to a group that belongs to another alternative part of the pattern, a backreference to a group that appears after the backreference, a backreference to a group that contains that backreference, or a backreference to a group that is inside a negative lookaround. However, by the specification, in any of these cases the backreference always ends up matching only zero-length (the empty string), regardless of the context in which the backreference and the group appear.
4
5 Backreferences that always successfully match zero-length and cannot match anything else are useless. They are basically ignored and can be removed without changing the behavior of the regular expression.
6
7 ```js
8 var regex = /^(?:(a)|\1b)$/;
9
10 regex.test("a"); // true
11 regex.test("b"); // true!
12 regex.test("ab"); // false
13
14 var equivalentRegex = /^(?:(a)|b)$/;
15
16 equivalentRegex.test("a"); // true
17 equivalentRegex.test("b"); // true
18 equivalentRegex.test("ab"); // false
19 ```
20
21 Useless backreference is a possible error in the code. It usually indicates that the regular expression does not work as intended.
22
23 ## Rule Details
24
25 This rule aims to detect and disallow the following backreferences in regular expression:
26
27 * Backreference to a group that is in another alternative, e.g., `/(a)|\1b/`. In such constructed regular expression, the backreference is expected to match what's been captured in, at that point, a non-participating group.
28 * Backreference to a group that appears later in the pattern, e.g., `/\1(a)/`. The group hasn't captured anything yet, and ECMAScript doesn't support forward references. Inside lookbehinds, which match backward, the opposite applies and this rule disallows backreference to a group that appears before in the same lookbehind, e.g., `/(?<=(a)\1)b/`.
29 * Backreference to a group from within the same group, e.g., `/(\1)/`. Similar to the previous, the group hasn't captured anything yet, and ECMAScript doesn't support nested references.
30 * Backreference to a group that is in a negative lookaround, if the backreference isn't in the same negative lookaround, e.g., `/a(?!(b)).\1/`. A negative lookaround (lookahead or lookbehind) succeeds only if its pattern cannot match, meaning that the group has failed.
31
32 By the ECMAScript specification, all backreferences listed above are valid, always succeed to match zero-length, and cannot match anything else. Consequently, they don't produce parsing or runtime errors, but also don't affect the behavior of their regular expressions. They are syntactically valid but useless.
33
34 This might be surprising to developers coming from other languages where some of these backreferences can be used in a meaningful way.
35
36 ```js
37 // in some other languages, this pattern would successfully match "aab"
38
39 /^(?:(a)(?=a)|\1b)+$/.test("aab"); // false
40 ```
41
42 Examples of **incorrect** code for this rule:
43
44 ```js
45 /*eslint no-useless-backreference: "error"*/
46
47 /^(?:(a)|\1b)$/; // reference to (a) into another alternative
48
49 /^(?:(a)|b(?:c|\1))$/; // reference to (a) into another alternative
50
51 /^(?:a|b(?:(c)|\1))$/; // reference to (c) into another alternative
52
53 /\1(a)/; // forward reference to (a)
54
55 RegExp('(a)\\2(b)'); // forward reference to (b)
56
57 /(?:a)(b)\2(c)/; // forward reference to (c)
58
59 /\k<foo>(?<foo>a)/; // forward reference to (?<foo>a)
60
61 /(?<=(a)\1)b/; // backward reference to (a) from within the same lookbehind
62
63 /(?<!(a)\1)b/; // backward reference to (a) from within the same lookbehind
64
65 new RegExp('(\\1)'); // nested reference to (\1)
66
67 /^((a)\1)$/; // nested reference to ((a)\1)
68
69 /a(?<foo>(.)b\1)/; // nested reference to (?<foo>(.)b\1)
70
71 /a(?!(b)).\1/; // reference to (b) into a negative lookahead
72
73 /(?<!(a))b\1/; // reference to (a) into a negative lookbehind
74 ```
75
76 Examples of **correct** code for this rule:
77
78 ```js
79 /*eslint no-useless-backreference: "error"*/
80
81 /^(?:(a)|(b)\2)$/; // reference to (b)
82
83 /(a)\1/; // reference to (a)
84
85 RegExp('(a)\\1(b)'); // reference to (a)
86
87 /(a)(b)\2(c)/; // reference to (b)
88
89 /(?<foo>a)\k<foo>/; // reference to (?<foo>a)
90
91 /(?<=\1(a))b/; // reference to (a), correctly before the group as they're in the same lookbehind
92
93 /(?<=(a))b\1/; // reference to (a), correctly after the group as the backreference isn't in the lookbehind
94
95 new RegExp('(.)\\1'); // reference to (.)
96
97 /^(?:(a)\1)$/; // reference to (a)
98
99 /^((a)\2)$/; // reference to (a)
100
101 /a(?<foo>(.)b\2)/; // reference to (.)
102
103 /a(?!(b|c)\1)./; // reference to (b|c), correct as it's from within the same negative lookahead
104
105 /(?<!\1(a))b/; // reference to (a), correct as it's from within the same negative lookbehind
106 ```
107
108 Please note that this rule does not aim to detect and disallow a potentially erroneous use of backreference syntax in regular expressions, like the use in character classes or an attempt to reference a group that doesn't exist. Depending on the context, a `\1`...`\9` sequence that is not a syntactically valid backreference may produce syntax error, or be parsed as something else (e.g., as a legacy octal escape sequence).
109
110 Examples of additional **correct** code for this rule:
111
112 ```js
113 /*eslint no-useless-backreference: "error"*/
114
115 // comments describe behavior in a browser
116
117 /^[\1](a)$/.test("\x01a"); // true. In a character class, \1 is treated as an octal escape sequence.
118 /^\1$/.test("\x01"); // true. Since the group 1 doesn't exist, \1 is treated as an octal escape sequence.
119 /^(a)\1\2$/.test("aa\x02"); // true. In this case, \1 is a backreference, \2 is an octal escape sequence.
120 ```
121
122 ## Further Reading
123
124 * [MDN: Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
125
126 ## Related Rules
127
128 * [no-control-regex](no-control-regex.md)
129 * [no-empty-character-class](no-empty-character-class.md)
130 * [no-invalid-regexp](no-invalid-regexp.md)