Preface
In the past, we were just used to accessing the regular matched groups through array subscripts, but when the groups reach 4 or 5, it would be very troublesome to identify them. V8 has long implemented the regular naming grouping proposal, but we rarely use it. This article will introduce the regular naming grouping of JS.
Past practices
Suppose we want to use regular matches to a date, in the past we would do this:
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/; const matchObj = RE_DATE.exec('1999-12-31'); const year = matchObj[1]; // 1999 const month = matchObj[2]; // 12 const day = matchObj[3]; // 31
Here are a few disadvantages:
- To find a grouped position, you have to go to the brackets, and sometimes nesting it can be more troublesome.
- When students who maintain the code read, they must find the corresponding brackets in the rules based on the subscript, and read the rules in the brackets again to know the meaning.
- When you adjust the number, order, or nesting of regular capture groups, you must also make adjustments to the following code.
All these problems can be solved by regular named grouping.
How to play now
Now you just need to give the group a named identifier:
(?<year>\d{4})
Here, we tagged the previous capture group #1 with the variable year. The name must be a legal JavaScript identifier. After matching, you can access the captured string by accessing.
Let's rewrite the previous code by naming grouping:
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const matchObj = RE_DATE.exec('1999-12-31'); const year = ; // 1999 const month = ; // 12 const day = ; // 31
If there is a named group in the regular, the matching result will have an additional group attribute, which contains the capture results of all named groups. In conjunction with the use of the above-deconstruction method, it is another clear stream:
const {groups: {day, year}} = RE_DATE.exec('1999-12-31'); (year); // 1999 (day); // 31
Of course, even if you use named grouping, the returned results can still be accessed through the previous array subscript:
const year2 = matchObj[1]; // 1999 const month2 = matchObj[2]; // 12 const day2 = matchObj[3]; // 31
Naming grouping has the following advantages:
- It is easier to find the "ID" of the group.
- The matching code becomes self-descriptive because the ID of the packet describes the captured content.
- If you change the order of groupings, you do not have to change the matching code.
- The names of groups also make regular expressions easier to understand, as you can see directly what each group is for.
Backreferences
Backreference named grouping\k<name>
See the following example of matching repeated words:
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/; RE_TWICE.test('abc!abc'); // true RE_TWICE.test('abc!ab'); // false
At the same time, you can also use the previous backreference method:
const RE_TWICE = /^(?<word>[a-z]+)!\1$/; RE_TWICE.test('abc!abc'); // true RE_TWICE.test('abc!ab'); // false
replace( )
The string method replace() supports named grouping in two ways:
Method one
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; ('1999-12-31'.replace(RE_DATE, '$<month>/$<day>/$<year>')); // 12/31/1999
If replace does not necessarily return a new splice string directly, then you can take a look at the following method:
Method 2
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; ('1999-12-31'.replace( RE_DATE, (g, y, m, d, offset, input, {year, month, day}) => month+'/'+day+'/'+year)); // 12/31/1999
Look at the callback of the replace, and it is so nervous that it is not useful. Let’s take a look at the simpler way to write it:
('1999-12-31'.replace(RE_DATE, (...args) => { const {year, month, day} = (-1)[0]; return month+'/'+day+'/'+year; })); // 12/31/1999
Here, we use the spread operator to directly take the last parameter, and then connect to the previous deconstruction method, and the result is another clear stream.
No matching result for named grouping?
If the optional named group does not match, its attribute value is set to undefined, but the key is still present:
const RE_OPT_A = /^(?<as>a+)?$/; const matchObj = RE_OPT_A.exec(''); // We have a match: (matchObj[0] === ''); // true // Group <as> didn't match anything: ( === undefined); // true // But property as exists: ('as' in ); // true
Exception
There cannot be duplicates for group names:
/(?<foo>a)(?<foo>b)/ // SyntaxError: Duplicate capture group name
Backreferences to a non-existent group name:
/\k<foo>/u // SyntaxError: Invalid named capture referenced /\k<foo>/.test("k<foo>") // true, No Unicode For backward compatibility,k The front \ Will be discarded
Refer to a non-existent group in the replacement string of the reapplce() method:
"abc".replace(/(?<foo>.*)/, "$<bar>") // SyntaxError: Invalid replacement string "abc".replace(/(.*)/, "$<bar>") // "$<bar>",Backward compatibility when no named grouping is included
at last
- Chrome 60 supports named grouping
- Handle compatibility issues through babel plugin
babel-plugin-transform-modern-regexp
Summarize
The above is the JavaScript regular naming group introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support for my website!