bash regular expression point “.” character not matching
Clash Royale CLAN TAG#URR8PPP
up vote
0
down vote
favorite
The string I'm trying to match is an ip address and I've seens quite some examples on the web. However it appears that I'm missing something which may or may not have to do with the differences between regexp conventions. (pcre, ere, ??)
To break it down to the point I'm missing here's the partial ip address that I'm trying to get matched:
ip="255.255."
This is a regular expression that tries to match above ip:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2
It's bash so I've got this to compare:
[[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
Alas, it doesn't match.
As far as I know, I'm allowed to escape the . because I want it to match a point character, not just any character. (what . stands for in regexp to the best of my knowledge.)
This is what happens when I remove the escape before the point to illustrate above statement:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
ok
# ip="255X255Y"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9] [0-9]?.)2 ]] && echo "ok"
ok
That's not correct to match (partial) ip in this case.
Why does it not match this:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
There are two groups and each of them is "255." and that part matches just fine like this:
# ip="255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.) ]] && echo "ok" || echo "nope"
ok
EDIT: some extra info that possibly solves my issue:
just noticed the following:
# ip="172.15.11.10"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
# ip="172.15."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
And when the following grouping is made:
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
So grouping the "number" part in front of the seperator "point" solves the issue?
# ip="255.255."
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
I'm inclined to think this solves it however I do not yet understand why.
EDIT: the full regexp for the ip address is this here:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
This is the same mentioned by Jeff in below answer.
bash regular-expression
add a comment |
up vote
0
down vote
favorite
The string I'm trying to match is an ip address and I've seens quite some examples on the web. However it appears that I'm missing something which may or may not have to do with the differences between regexp conventions. (pcre, ere, ??)
To break it down to the point I'm missing here's the partial ip address that I'm trying to get matched:
ip="255.255."
This is a regular expression that tries to match above ip:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2
It's bash so I've got this to compare:
[[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
Alas, it doesn't match.
As far as I know, I'm allowed to escape the . because I want it to match a point character, not just any character. (what . stands for in regexp to the best of my knowledge.)
This is what happens when I remove the escape before the point to illustrate above statement:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
ok
# ip="255X255Y"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9] [0-9]?.)2 ]] && echo "ok"
ok
That's not correct to match (partial) ip in this case.
Why does it not match this:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
There are two groups and each of them is "255." and that part matches just fine like this:
# ip="255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.) ]] && echo "ok" || echo "nope"
ok
EDIT: some extra info that possibly solves my issue:
just noticed the following:
# ip="172.15.11.10"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
# ip="172.15."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
And when the following grouping is made:
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
So grouping the "number" part in front of the seperator "point" solves the issue?
# ip="255.255."
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
I'm inclined to think this solves it however I do not yet understand why.
EDIT: the full regexp for the ip address is this here:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
This is the same mentioned by Jeff in below answer.
bash regular-expression
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
The string I'm trying to match is an ip address and I've seens quite some examples on the web. However it appears that I'm missing something which may or may not have to do with the differences between regexp conventions. (pcre, ere, ??)
To break it down to the point I'm missing here's the partial ip address that I'm trying to get matched:
ip="255.255."
This is a regular expression that tries to match above ip:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2
It's bash so I've got this to compare:
[[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
Alas, it doesn't match.
As far as I know, I'm allowed to escape the . because I want it to match a point character, not just any character. (what . stands for in regexp to the best of my knowledge.)
This is what happens when I remove the escape before the point to illustrate above statement:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
ok
# ip="255X255Y"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9] [0-9]?.)2 ]] && echo "ok"
ok
That's not correct to match (partial) ip in this case.
Why does it not match this:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
There are two groups and each of them is "255." and that part matches just fine like this:
# ip="255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.) ]] && echo "ok" || echo "nope"
ok
EDIT: some extra info that possibly solves my issue:
just noticed the following:
# ip="172.15.11.10"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
# ip="172.15."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
And when the following grouping is made:
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
So grouping the "number" part in front of the seperator "point" solves the issue?
# ip="255.255."
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
I'm inclined to think this solves it however I do not yet understand why.
EDIT: the full regexp for the ip address is this here:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
This is the same mentioned by Jeff in below answer.
bash regular-expression
The string I'm trying to match is an ip address and I've seens quite some examples on the web. However it appears that I'm missing something which may or may not have to do with the differences between regexp conventions. (pcre, ere, ??)
To break it down to the point I'm missing here's the partial ip address that I'm trying to get matched:
ip="255.255."
This is a regular expression that tries to match above ip:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2
It's bash so I've got this to compare:
[[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
Alas, it doesn't match.
As far as I know, I'm allowed to escape the . because I want it to match a point character, not just any character. (what . stands for in regexp to the best of my knowledge.)
This is what happens when I remove the escape before the point to illustrate above statement:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok"
ok
# ip="255X255Y"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9] [0-9]?.)2 ]] && echo "ok"
ok
That's not correct to match (partial) ip in this case.
Why does it not match this:
# ip="255.255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
There are two groups and each of them is "255." and that part matches just fine like this:
# ip="255."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.) ]] && echo "ok" || echo "nope"
ok
EDIT: some extra info that possibly solves my issue:
just noticed the following:
# ip="172.15.11.10"
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
# ip="172.15."
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
ok
And when the following grouping is made:
# [[ $ip =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)2 ]] && echo "ok" || echo "nope"
nope
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
So grouping the "number" part in front of the seperator "point" solves the issue?
# ip="255.255."
# [[ $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2 ]] && echo "ok" || echo "nope"
ok
I'm inclined to think this solves it however I do not yet understand why.
EDIT: the full regexp for the ip address is this here:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
This is the same mentioned by Jeff in below answer.
bash regular-expression
bash regular-expression
edited Nov 21 at 15:05
asked Nov 21 at 14:26
lievendp
416
416
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
The parenthesis were in the wrong place.
In the failing regex, you had grouped the octet's possibilities together with alternations:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)
... which would match the beginning of line ^
followed by:
25[0-5]
or2[0-4][0-9]
or[01]?[0-9][0-9]?.
Notice how the period is part of the 3rd possible alternation. That forces the regex to match the initial 255
, leaving the following period unmatched.
You want the octet and the period to be repeated, so group the regex like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2
or like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
... so that there are four octets.
That forces the IP address to appear by itself on a line. If you don't care where in the line the IP address shows up, then drop the leading (^
) and trailing ($
) anchors.
On Linux, for a visual aid in testing, you could use grep --color=always -E ...
, for instance:
$ ip=jeff-255.255.255.255-foo
$ echo "$ip" | grep --color=always -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
jeff-255.255.255.255-foo
... where the 255.255.255.255
shows up in color.
thanks for the explanation, so the grouping was wrong and this made "." become a part of the last possible alteration from the list. it works great now. Also thanks for the coloring option, I never looked at that before. :-)
– lievendp
Nov 21 at 15:07
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
The parenthesis were in the wrong place.
In the failing regex, you had grouped the octet's possibilities together with alternations:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)
... which would match the beginning of line ^
followed by:
25[0-5]
or2[0-4][0-9]
or[01]?[0-9][0-9]?.
Notice how the period is part of the 3rd possible alternation. That forces the regex to match the initial 255
, leaving the following period unmatched.
You want the octet and the period to be repeated, so group the regex like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2
or like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
... so that there are four octets.
That forces the IP address to appear by itself on a line. If you don't care where in the line the IP address shows up, then drop the leading (^
) and trailing ($
) anchors.
On Linux, for a visual aid in testing, you could use grep --color=always -E ...
, for instance:
$ ip=jeff-255.255.255.255-foo
$ echo "$ip" | grep --color=always -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
jeff-255.255.255.255-foo
... where the 255.255.255.255
shows up in color.
thanks for the explanation, so the grouping was wrong and this made "." become a part of the last possible alteration from the list. it works great now. Also thanks for the coloring option, I never looked at that before. :-)
– lievendp
Nov 21 at 15:07
add a comment |
up vote
3
down vote
accepted
The parenthesis were in the wrong place.
In the failing regex, you had grouped the octet's possibilities together with alternations:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)
... which would match the beginning of line ^
followed by:
25[0-5]
or2[0-4][0-9]
or[01]?[0-9][0-9]?.
Notice how the period is part of the 3rd possible alternation. That forces the regex to match the initial 255
, leaving the following period unmatched.
You want the octet and the period to be repeated, so group the regex like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2
or like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
... so that there are four octets.
That forces the IP address to appear by itself on a line. If you don't care where in the line the IP address shows up, then drop the leading (^
) and trailing ($
) anchors.
On Linux, for a visual aid in testing, you could use grep --color=always -E ...
, for instance:
$ ip=jeff-255.255.255.255-foo
$ echo "$ip" | grep --color=always -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
jeff-255.255.255.255-foo
... where the 255.255.255.255
shows up in color.
thanks for the explanation, so the grouping was wrong and this made "." become a part of the last possible alteration from the list. it works great now. Also thanks for the coloring option, I never looked at that before. :-)
– lievendp
Nov 21 at 15:07
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
The parenthesis were in the wrong place.
In the failing regex, you had grouped the octet's possibilities together with alternations:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)
... which would match the beginning of line ^
followed by:
25[0-5]
or2[0-4][0-9]
or[01]?[0-9][0-9]?.
Notice how the period is part of the 3rd possible alternation. That forces the regex to match the initial 255
, leaving the following period unmatched.
You want the octet and the period to be repeated, so group the regex like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2
or like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
... so that there are four octets.
That forces the IP address to appear by itself on a line. If you don't care where in the line the IP address shows up, then drop the leading (^
) and trailing ($
) anchors.
On Linux, for a visual aid in testing, you could use grep --color=always -E ...
, for instance:
$ ip=jeff-255.255.255.255-foo
$ echo "$ip" | grep --color=always -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
jeff-255.255.255.255-foo
... where the 255.255.255.255
shows up in color.
The parenthesis were in the wrong place.
In the failing regex, you had grouped the octet's possibilities together with alternations:
^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.)
... which would match the beginning of line ^
followed by:
25[0-5]
or2[0-4][0-9]
or[01]?[0-9][0-9]?.
Notice how the period is part of the 3rd possible alternation. That forces the regex to match the initial 255
, leaving the following period unmatched.
You want the octet and the period to be repeated, so group the regex like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)2
or like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
... so that there are four octets.
That forces the IP address to appear by itself on a line. If you don't care where in the line the IP address shows up, then drop the leading (^
) and trailing ($
) anchors.
On Linux, for a visual aid in testing, you could use grep --color=always -E ...
, for instance:
$ ip=jeff-255.255.255.255-foo
$ echo "$ip" | grep --color=always -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)3(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
jeff-255.255.255.255-foo
... where the 255.255.255.255
shows up in color.
edited Nov 24 at 4:39
answered Nov 21 at 14:45
Jeff Schaller
36.6k1052120
36.6k1052120
thanks for the explanation, so the grouping was wrong and this made "." become a part of the last possible alteration from the list. it works great now. Also thanks for the coloring option, I never looked at that before. :-)
– lievendp
Nov 21 at 15:07
add a comment |
thanks for the explanation, so the grouping was wrong and this made "." become a part of the last possible alteration from the list. it works great now. Also thanks for the coloring option, I never looked at that before. :-)
– lievendp
Nov 21 at 15:07
thanks for the explanation, so the grouping was wrong and this made "." become a part of the last possible alteration from the list. it works great now. Also thanks for the coloring option, I never looked at that before. :-)
– lievendp
Nov 21 at 15:07
thanks for the explanation, so the grouping was wrong and this made "." become a part of the last possible alteration from the list. it works great now. Also thanks for the coloring option, I never looked at that before. :-)
– lievendp
Nov 21 at 15:07
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f483221%2fbash-regular-expression-point-character-not-matching%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown