The next concept we'll cover is called pattern matching. Pattern matching allows us to create extension patterns in our dialplan that match more than one possible dialed number. Pattern matching saves us from having to create an extension in the dialplan for every possible number that might be dialed.
When Alice dials a number on her phone, Asterisk first looks for an extension (in the context specified by the channel driver configuration) that matches exactly what Alice dialed. If there's no exact match, Asterisk then looks for a pattern that matches. After we show the syntax and some basic examples of pattern matching, we'll explain how Asterisk finds the best match if there are two or more patterns which match the dialed number.
Special Characters Used in Pattern Matching
Pattern matches always begin with an underscore. This is how Asterisk recognizes that the extension is a pattern and not just an extension with a funny name. Within the pattern, we use various letters and characters to represent sets or ranges of numbers. Here are the most common letters:
X
The letter X or x represents a single digit from 0 to 9.
Z
The letter Z or z represents any digit from 1 to 9.
N
The letter N or n matches any digit from 2-9.
Ranges used in Pattern Matching
A numeric range can be used to match against a dialed number. This is also called a Character Set
[1237-9]
This pattern matches any digit or letter in the brackets. In this example, the pattern will match: 1,2,3,7,8,9
Wilcards used in Pattern Matching
The following special characters are considered wildcards
- . The '.' character matches one or more characters
- ! The '!' character matches zero or more characters immediately
The exclamation mark wildcard (!), behaves specially and will be further explained below in 'Other Special Characters' below.
Please make sure to read 'Be Careful With Wildcards in Pattern Matches' below.
Basic Example
Now let's look at a sample pattern. If you wanted to match all four-digit numbers that had the first two digits as six and four, you would create an extension that looks like:
exten => _64XX,1,SayDigits(${EXTEN})
In this example, each X represents a single digit, with any value from zero to nine.
The above pattern will match the following examples:
- 6400
- 6401
- 6450
- 6499
We're essentially saying "The first digit must be a six, the second digit must be a four, the third digit can be anything from zero to nine, and the fourth digit can be anything from zero to nine".
Complex Examples
Lets use some Character Sets and Wildcards
exten => _64X[4-9],1,SayDigits(${EXTEN}) exten => _[6-4]4[4-9],1,SayDigits(${EXTEN}) exten => _64.,1,SayDigits(${EXTEN})
The first example: The first must be a six, the second digit must be a four, the third digit can be anything from zero to nine, and the fourth digit must be between four and nine
The second example: The first digit must be between six and four, the second digit must be four, the third digit must be between four and nine
The third example: The first digit must be a six, the second digit must be a four, the third digit can be anything at all (including letters), and we will continue to collect digits until the user stops entering digits
Character Sets
If we want to be more specific about a range of numbers, we can put those numbers or number ranges in square brackets to define a character set. For example, what if we wanted the second digit to be either a three or a four? One way would be to create two patterns (_64XX and _63XX), but a more compact method would be to do _6[34]XX. This specifies that the first digit must be a six, the second digit can be either a three or a four, and that the last two digits can be anything from zero to nine.
You can also use ranges within square brackets. For example, [1-468] would match a single digit from one through four or six or eight. It does not match any number from one to four hundred sixty-eight!
Other Special Characters
Within Asterisk patterns, we can also use a couple of other characters to represent ranges of numbers. The period character (.) at the end of a pattern matches one or more remaining characters. You put it at the end of a pattern when you want to match extensions of an indeterminate length. As an example, the pattern _9876. would match any number that began with 9876 and had at least one more character or digit.
The exclamation mark (!) character is similar to the period and matches zero or more remaining characters. It is used in overlap dialing to dial through Asterisk. For example, _9876! would match any number that began with 9876 including 9876, and would respond that the number was complete as soon as there was an unambiguous match.
Order of Pattern Matching
Now let's show what happens when there is more than one pattern that matches the dialed number. How does Asterisk know which pattern to choose as the best match?
Asterisk uses a simple set of rules to sort the extensions and patterns so that the best match is found first. The best match is simply the most specific pattern. The sorting rules are:
- The dash (-) character is ignored in extensions and patterns except when it is used in a pattern to specify a range in a character set. It has no effect in matching or sorting extensions.
- Non-pattern extensions are sorted in ASCII sort order before patterns.
- Patterns are sorted by the most constrained character set per digit first. By most constrained, we mean the pattern that has the fewest possible matches for a digit. As an example, the N character has eight possible matches (two through nine), while X has ten possible matches (zero through nine) so N sorts first.
- Character sets that have the same number of characters are sorted in ASCII sort order as if the sets were strings of the set characters. As an example, X is 0123456789 and [a-j] is abcdefghij so X sorts first. This sort ordering is important if the character sets overlap as with [0-4] and [4-8].
- The period (.) wildcard sorts after character sets.
- The exclamation mark (!) wildcard sorts after the period wildcard.
Let's look at an example to better understand how this works. Let's assume Alice dials extension 6421, and she has the following patterns in her dialplan:
exten => _6XX1,1,SayAlpha(A) exten => _64XX,1,SayAlpha(B) exten => _640X,1,SayAlpha(C) exten => _6.,1,SayAlpha(D) exten => _64NX,1,SayAlpha(E) exten => _6[45]NX,1,SayAlpha(F) exten => _6[34]NX,1,SayAlpha(G)
Can you tell (without reading ahead) which one would match?
Using the sorting rules explained above, the extensions sort as follows:
_640X sorts before _64NX because of rule 3 at position 4. (0 before N)
_64NX sorts before _64XX because of rule 3 at position 4. (N before X)
_64XX sorts before _6[34]NX because of rule 3 at position 3. (4 before [34])
_6[34]NX sorts before _6[45]NX because of rule 4 at position 3. ([34] before [45])
_6[45]NX sorts before _6XX1 because of rule 3 at position 3. ([45] before X)
_6XX1 sorts before _6. because of rule 5 at position 3. (X before .)
exten => _640X,1,SayAlpha(C) exten => _64NX,1,SayAlpha(E) exten => _64XX,1,SayAlpha(B) exten => _6[34]NX,1,SayAlpha(G) exten => _6[45]NX,1,SayAlpha(F) exten => _6XX1,1,SayAlpha(A) exten => _6.,1,SayAlpha(D)
When Alice dials 6421, Asterisk searches through its list of sorted extensions and uses the first matching extension. In this case _64NX is found.
To verify that Asterisk actually does sort the extensions in the manner that we've shown, add the following extensions to the [users] context of your own dialplan.
exten => _6XX1,1,SayAlpha(A) exten => _64XX,1,SayAlpha(B) exten => _640X,1,SayAlpha(C) exten => _6.,1,SayAlpha(D) exten => _64NX,1,SayAlpha(E) exten => _6[45]NX,1,SayAlpha(F) exten => _6[34]NX,1,SayAlpha(G)
Reload the dialplan, and then type dialplan show [email protected] at the Asterisk CLI. Asterisk will show you all extensions that match in the [users] context. If you were to dial extension 6421 in the [users] context the first found extension will execute.
server*CLI> dialplan show [email protected] [ Context 'users' created by 'pbx_config' ] '_64NX' => 1. SayAlpha(E) [pbx_config] '_64XX' => 1. SayAlpha(B) [pbx_config] '_6[34]NX' => 1. SayAlpha(G) [pbx_config] '_6[45]NX' => 1. SayAlpha(F) [pbx_config] '_6XX1' => 1. SayAlpha(A) [pbx_config] '_6.' => 1. SayAlpha(D) [pbx_config] -= 6 extensions (6 priorities) in 1 context. =-
server*CLI> dialplan show users [ Context 'users' created by 'pbx_config' ] '_640X' => 1. SayAlpha(C) [pbx_config] '_64NX' => 1. SayAlpha(E) [pbx_config] '_64XX' => 1. SayAlpha(B) [pbx_config] '_6[34]NX' => 1. SayAlpha(G) [pbx_config] '_6[45]NX' => 1. SayAlpha(F) [pbx_config] '_6XX1' => 1. SayAlpha(A) [pbx_config] '_6.' => 1. SayAlpha(D) [pbx_config] -= 7 extensions (7 priorities) in 1 context. =-
You can dial extension 6421 to try it out on your own.
Matching on Caller ID
Within an extension handler, it is also possible to match based upon the Caller ID of the incoming channel by appending a forward slash to the dialed extension or pattern, followed by a Caller ID pattern to be matched. Consider the following example, featuring phones with Caller IDs of 101, 102 and 103.
exten => 306,1,NoOp() same => n,Background(goodbye) same => n,Hangup() exten => 306/_101,1,NoOp() same => n,Background(year) same => n,Hangup() exten => 306/_102,1,NoOp() same => n,Background(beep) same => n,Hangup()
The phone with Caller ID 101, when dialing 306, will hear the prompt "year" and will be hung up. The phone with Caller ID 102, when dialing 306, will hear the "beep" sound and will be hung up. The phone with Caller ID 103, or any other caller, when dialing 306, will hear the "goodbye" prompt and will be hung up.
14 Comments
Olaf Winkler
I'm missing an explanation concerning the (non)availibility of combinations of special letters (X N Z) and ranges / other characters within alternative brackets, e.g.
_[+X]X. will not match the intended match as _[+0-9]X. would.
As this behaviour is different from usual regex-engins (assuming X N and Z are representig character classes) where character classes may be combined in an alternate definition in [], this should be mentioned here to avoid misunderstandings
Rusty Newton
Thanks for the note Olaf. I've modified the text to describe the expected behavior in a note.
Alexander Gonchiy
Just made that very miserable mistake, for the first time forgetting to put underscore before patterns...
I really think asterisk could be nice and optionally check those and warn during ael/dialplan reload, like this:
[2014-04-27 20:23:35] WARNING: file /etc/asterisk/main.ael, line 182-182: extension "89508[4-6]XXXXX" might be a pattern missing underscore (set code_dangerously=on in your dialplan to disable this check)
Rusty Newton
Hi Alexander. You can read on the wiki how we process feature requests. Here is a link.
Alexey Timonin
The behavior described in the sidenote (Be Careful with Pattern Matching) seems dangerous. Why would one want to have a fallthrough mechanics that silently hops between priorities of different extensions? Can it be disabled?
Richard Mudgett
That feature is intentional, useful, and not optional. You just need to be aware of the behaviour and structure your dialplan accordingly. The example given shows how it works and gives an idea of how it can be used.
Pgr
I still couldn't figure out, from this documentation, how I should match a single-digit extension.
I want a rule to match if a user dials 9, but not if he dials 9 followed by other digits.
Maybe the answer is something simple like just writing a _9 as a pattern?
Alexander Gonchiy
Yes. Both "9" (literal) and "_9" (pattern) would work.
Pgr
Thank you. Since this is a meant to be a precise specification, I suggest you include this in the very beginning: "a digit from 0 to 9 is interpreted as that exact digit at that position, not at any position." or something like it.
The reason this wasn't obvious to me (apart from my insufficient intelligence) was because I had tried it and it didn't work. Of course, the reason for not working was elsewhere... but if this spec is more complete, it is easier for us to weed out other, unrelated, ambiguities. Thanks!
Alexander Gonchiy
> When Alice dials a number on her phone, Asterisk first looks for an extension (in the context specified by the channel driver configuration) that matches exactly what Alice dialed
Here is how we know that extension "9" will match exactly "9".
> exten => _64XX,1,SayDigits(${EXTEN})
> In this example, each X represents a single digit, with any value from zero to nine.
> We're essentially saying "The first digit must be a six, the second digit must be a four, the third digit can be anything from zero to nine, and the fourth digit can be anything from zero to nine".
And here is how we know that "_9" matches exactly "9".
But I agree that this could be stated in even more explicit terms.
You can contribute to this documentation also.
Rusty Newton
This page covers the topic of pattern matching. Explicit extensions are covered in another page of the Dialplan section.
Contexts, Extensions, and Priorities
Bhushan Chaudhari
Hello All,
I need to write patter for matching if "999997" is there in between the number dialed:
For ex:
399999712345 => Should match as it has 3"999997"12345
14999997009988776 => Should also match as it has 14"999997"009988776
999997123456 => Should NOT match as there is no any number before string 999997
1423456999997 => Should NOT match as there is no any number after string 999997
Is this possible? please suggest.
Richard Mudgett
No, Asterisk itself cannot match extensions the way you describe. The only extension pattern matching rules built into Asterisk are on this page. You will have to use dialplan or AGI to further match extensions.
This wiki is not the place to ask questions like that. You should be asking this kind of question in other forums such as the community site or on the asterisk users mailing list.
https://community.asterisk.org/
Bhushan Chaudhari
Thanks for the suggestion Richard.
I will explore dialplan/AGI as you suggested and will ask further queries, if any, on community site.