Capturing groups
When using pattern()->match()
and pattern()->replace->callback()
, some methods receive a callback that accepts Detail
details object. These methods are: first()
, findFirst()
, forEach()
, map()
, flatMap()
, callback()
.
The details can be used to get concise information about the matched occurrence, such as its value
(i.e. "the whole match"
), capturing groups and their UTF-8/raw offsets, limits, indexes, other matches as well as the
used subject (although it could also be pass as a closure parameter) and more.
note
#
OverviewUsing Detail
, you gain access complete information about capturing groups:
get(int|string)
- capturing group text valuegroup(int|string)
- capturing group details, with:text()
- value of the group, asstring
toInt()
- value of the group, cast toint
isInt()
- whether the group is a valid integer (e.g.true
for group(\d+)
)- offsets of matched values in the subject:
- character offsets (UTF-8 safe) -
offset()
- byte offsets -
byteOffset()
- character offsets (UTF-8 safe) -
orReturn()
/orElse()
/orThrow()
- returns a group, or controls the absence of the groupindex()
- ordinal value of the capturing group in a patternname()
- name of the capturing group, ornull
of group is not namedusedIdentifier()
- eitherindex()
orname()
, depending on the argument ofgroup(int|string)
all()
- other matched occurrences of the groupmatched(int|string)
- whether the group was matched by the subjecthasGroup(int|string)
- whether group was used in a patternGroupName::isValid(string)
- whether group name has proper formatgroups()
/namedGroups()
- interface for composite operations for all groupsgroupNames()
- string list of named groups used in a patterngroupsCount()
- counts number of capturing groups (without duplicates of named and regular groups)
note
All types of group syntax: (?<name>)
, (?'name')
and (?P<name>)
are considered "named". Regular, indexed groups
are use with syntax ()
. Group (?:)
is considered a non-capturing group.
#
Group textTo get a value of a capturing group from, use Detail.get()
:
#
Group detailsYou can chain Detail.group()
with a variety of methods, you can use to get
more details about the group.
#
Offsets#
Optional groupsSome patterns contain required capturing groups, e.g ^(cm|mm)$
. Others, have capturing groups that are optional,
e.g. \d+(cm|mm)?
. As you can see, in \d+(cm|mm)?
, group (cm|mm)
doesn't have to be matched for the whole
subject to be matched - both "14"
and "14cm"
are subjects that match the pattern.
Optional groups allow you to deal with potentially unmatched groups with elegance. If the group is matched,
each of the methods: text()
/ orReturn()
/ orElse()
/ orThrow()
work exactly the same - returns the value of
the matched capturing group.
The difference is - how they work when the group is not matched:
Method group()->orThrow()
works exactly the same as findFirst()->orThrow()
, which means it accepts user defined
exception to instantiate:
note
Method group()->orThrow()
throws GroupNotMatchedException
by default, so - when called without user defined exception -
it's actually identical to group()->text()
.
note
Method group()->orElse(callable)
callback receives NotMatched
, just like findFirst()->orElse()
.
#
Index, name and identifierGroups can be referred to either by an index or by name, if the group in a pattern is named. What was the group referred with is called an identifier. If group was referred to by an index, then the index is the identifier.
T-Regx has 3 separate methods for each of the group reference method:
index()
- returns the ordinal number of a groupname()
- returns the name of a group, ornull
if the group is not namedusedIdentifier()
- returns eitherindex()
orname()
, depending on what was the group referred with
#
Optional GroupsMethod matched(int|string)
allows you to verify whether a given group was matched by the subject:
It'll work just as well with named groups:
Although method $detail->matched(int|string)
is the preferred way - same effect can be achieved with
using $detail->group(int|string)->matched()
:
#
Invalid groups and argumentsmatched()
will throwNonexistentGroupException
, when used with a non-existent group (i.e.asdf
).matched()
will throw\InvalidArgumentException
, when used with an invalid group (i.e.2group
,-1
or any type other thanstring
orint
).
#
Nonexistent GroupsMethod hasGroup(int|string)
allows you to verify whether the group was used in a pattern:
It'll work just the same with regular (not named) groups:
#
Invalid groups and argumentshasGroup()
will throw\InvalidArgumentException
, when used with an invalid group (i.e.2group
,-1
or any type other thanstring
orint
).
note
Usages of hasGroup()
are rather infrequent, because rarely patterns are dynamic - they're constant much more often;
hence the developer doesn't have to check whether the group exists.
#
Invalid group namesWhen any group method is called with an invalid group name, for example:
then \InvalidArgumentException
is thrown.
To validate a group name before using it, you can use GroupName
helper:
#
Composite groupsDetail.groups()
and Detail.namedGroups()
return a list of capturing group values and offsets.
If a group is not matched, it will be represented as null
in the list.
#
Group namesMethod groupNames()
returns a simple string[]
with names of the capturing groups in order:
If a group isn't named, it's represented by null
:
#
Groups countMethod groupsCount()
returns the number of capturing groups (without duplicates of named and regular groups)
#
Other occurrencesMethod group()->all()
allows you to gain access to the occurrence of the group in other matches in the subject.
If the group is not matched in other occurrences, its value in all()
result array will be null
:
In other words Detail.group($x).all()
is a collection of occurrences of group $x
in all other matches.
J
modifier#
Complication with note
Complication with J
modifier is a rather advanced matter, and not necessary for everyday use.
If you don't seek "in-depth" understanding of capturing groups, feel free to skip this chapter.
To learn more, go to Capturing groups - J modifier.
#
Groups In-Depthnote
Groups In-Depth is a rather advanced matter, and not necessary for everyday use. If you don't seek "in-depth" understanding of capturing groups, feel free to skip this chapter.
To learn more, go to Capturing groups - in depth.