Regex expression for IP address/CIDR in bash

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0















I want to check if the user input is a valid IP address/CIDR in bash and I am using regular expressions to do that. So valid CIDR should be 0-32 and for IP from (1-254).(1-255).(1-255).(1-255)/(1-32) So my code currently is:



read -p "Input: " ip_address

if [[ $ip_address =~ ^[0-9]+.[0-9]+.[0-9]+.[0-9]+/[0-9]+$ ]];
then
echo "VALID"
else
echo "NOT VALID"
fi


But it is too generous and accepts some not valid combinations.
So a valid IP address/CIDR combination should be: 10.11.11.11/24 or 254.255.255.255/23 and invalid will be 256.19.11.11/24 because the first octet is higher than 255 or 222.222.222.222/33 here the CIDR is is higher than 32.
Is there another way apart of regex to check for valid IP address/CIDR?










share|improve this question

















  • 1





    If you have the option to use Python, look at cyruslab.net/2018/04/10/pythonvalidate-an-ip-address

    – Raman Sailopal
    Mar 8 at 12:03

















0















I want to check if the user input is a valid IP address/CIDR in bash and I am using regular expressions to do that. So valid CIDR should be 0-32 and for IP from (1-254).(1-255).(1-255).(1-255)/(1-32) So my code currently is:



read -p "Input: " ip_address

if [[ $ip_address =~ ^[0-9]+.[0-9]+.[0-9]+.[0-9]+/[0-9]+$ ]];
then
echo "VALID"
else
echo "NOT VALID"
fi


But it is too generous and accepts some not valid combinations.
So a valid IP address/CIDR combination should be: 10.11.11.11/24 or 254.255.255.255/23 and invalid will be 256.19.11.11/24 because the first octet is higher than 255 or 222.222.222.222/33 here the CIDR is is higher than 32.
Is there another way apart of regex to check for valid IP address/CIDR?










share|improve this question

















  • 1





    If you have the option to use Python, look at cyruslab.net/2018/04/10/pythonvalidate-an-ip-address

    – Raman Sailopal
    Mar 8 at 12:03













0












0








0








I want to check if the user input is a valid IP address/CIDR in bash and I am using regular expressions to do that. So valid CIDR should be 0-32 and for IP from (1-254).(1-255).(1-255).(1-255)/(1-32) So my code currently is:



read -p "Input: " ip_address

if [[ $ip_address =~ ^[0-9]+.[0-9]+.[0-9]+.[0-9]+/[0-9]+$ ]];
then
echo "VALID"
else
echo "NOT VALID"
fi


But it is too generous and accepts some not valid combinations.
So a valid IP address/CIDR combination should be: 10.11.11.11/24 or 254.255.255.255/23 and invalid will be 256.19.11.11/24 because the first octet is higher than 255 or 222.222.222.222/33 here the CIDR is is higher than 32.
Is there another way apart of regex to check for valid IP address/CIDR?










share|improve this question














I want to check if the user input is a valid IP address/CIDR in bash and I am using regular expressions to do that. So valid CIDR should be 0-32 and for IP from (1-254).(1-255).(1-255).(1-255)/(1-32) So my code currently is:



read -p "Input: " ip_address

if [[ $ip_address =~ ^[0-9]+.[0-9]+.[0-9]+.[0-9]+/[0-9]+$ ]];
then
echo "VALID"
else
echo "NOT VALID"
fi


But it is too generous and accepts some not valid combinations.
So a valid IP address/CIDR combination should be: 10.11.11.11/24 or 254.255.255.255/23 and invalid will be 256.19.11.11/24 because the first octet is higher than 255 or 222.222.222.222/33 here the CIDR is is higher than 32.
Is there another way apart of regex to check for valid IP address/CIDR?







bash regular-expression ip






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 8 at 11:47









Georgе StoyanovGeorgе Stoyanov

164421




164421







  • 1





    If you have the option to use Python, look at cyruslab.net/2018/04/10/pythonvalidate-an-ip-address

    – Raman Sailopal
    Mar 8 at 12:03












  • 1





    If you have the option to use Python, look at cyruslab.net/2018/04/10/pythonvalidate-an-ip-address

    – Raman Sailopal
    Mar 8 at 12:03







1




1





If you have the option to use Python, look at cyruslab.net/2018/04/10/pythonvalidate-an-ip-address

– Raman Sailopal
Mar 8 at 12:03





If you have the option to use Python, look at cyruslab.net/2018/04/10/pythonvalidate-an-ip-address

– Raman Sailopal
Mar 8 at 12:03










1 Answer
1






active

oldest

votes


















2














To properly handle validation of an IP address or CIDR, use a library function specifically made for this, such as the cidrvalidate() Perl function in the Net::CIDR module:



$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/24
valid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/2
invalid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0
valid


See perldoc Net::CIDR for what else this library can do.



The -- are not necessary in the examples above but would be for arbitrary input from the user as otherwise, that input would be taken as an option by perl if it started with -.



The approaches below are variations on your attempt, which does not care about invalid netmasks.




A positive decimal integer between 0 and 255 may be matched by



[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]


A positive decimal integer between 0 and 32 may be matched by



[0-9]|[12][0-9]|3[012]


Using this:



#!/bin/bash

n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'

IFS= read -rp 'Input: ' ipaddr

if [[ $ipaddr =~ ^$n(.$n)3/$m$ ]]; then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


The expression



^$n(.$n)3/$m$


would expand to the full regular expression for a valid CIDR spanning the complete length of the given string.




The other obvious way to do this is to read the numbers in the given string and test whether the first four are in the 0-255 range and whether the fifth is in the range 0-32:



#!/bin/bash

IFS='./' read -rp 'Input: ' a b c d e

for var in "$a" "$b" "$c" "$d" "$e"; do
case $var in
""|*[!0123456789]*)
printf 'not a valid number: %sn' "$var"
exit 1
esac
done

ipaddr="$a.$b.$c.$d/$e"

if [ "$a" -ge 0 ] && [ "$a" -le 255 ] &&
[ "$b" -ge 0 ] && [ "$b" -le 255 ] &&
[ "$c" -ge 0 ] && [ "$c" -le 255 ] &&
[ "$d" -ge 0 ] && [ "$d" -le 255 ] &&
[ "$e" -ge 0 ] && [ "$e" -le 32 ]
then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


Here we read five words into five variables. The inputted string is split into words on . and / when read (which means 3/3/3/3.2 would be parsed as valid, but see $ipaddr in the code). Any non-integer data read would trigger the script to exit. We then start testing their values against the valid ranges. If any test fail, the address entered is not valid.






share|improve this answer

























  • thanks a lot for your help Stephane Chazelas and @Kusalananda

    – Georgе Stoyanov
    Mar 11 at 9:20











Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f505115%2fregex-expression-for-ip-address-cidr-in-bash%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














To properly handle validation of an IP address or CIDR, use a library function specifically made for this, such as the cidrvalidate() Perl function in the Net::CIDR module:



$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/24
valid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/2
invalid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0
valid


See perldoc Net::CIDR for what else this library can do.



The -- are not necessary in the examples above but would be for arbitrary input from the user as otherwise, that input would be taken as an option by perl if it started with -.



The approaches below are variations on your attempt, which does not care about invalid netmasks.




A positive decimal integer between 0 and 255 may be matched by



[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]


A positive decimal integer between 0 and 32 may be matched by



[0-9]|[12][0-9]|3[012]


Using this:



#!/bin/bash

n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'

IFS= read -rp 'Input: ' ipaddr

if [[ $ipaddr =~ ^$n(.$n)3/$m$ ]]; then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


The expression



^$n(.$n)3/$m$


would expand to the full regular expression for a valid CIDR spanning the complete length of the given string.




The other obvious way to do this is to read the numbers in the given string and test whether the first four are in the 0-255 range and whether the fifth is in the range 0-32:



#!/bin/bash

IFS='./' read -rp 'Input: ' a b c d e

for var in "$a" "$b" "$c" "$d" "$e"; do
case $var in
""|*[!0123456789]*)
printf 'not a valid number: %sn' "$var"
exit 1
esac
done

ipaddr="$a.$b.$c.$d/$e"

if [ "$a" -ge 0 ] && [ "$a" -le 255 ] &&
[ "$b" -ge 0 ] && [ "$b" -le 255 ] &&
[ "$c" -ge 0 ] && [ "$c" -le 255 ] &&
[ "$d" -ge 0 ] && [ "$d" -le 255 ] &&
[ "$e" -ge 0 ] && [ "$e" -le 32 ]
then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


Here we read five words into five variables. The inputted string is split into words on . and / when read (which means 3/3/3/3.2 would be parsed as valid, but see $ipaddr in the code). Any non-integer data read would trigger the script to exit. We then start testing their values against the valid ranges. If any test fail, the address entered is not valid.






share|improve this answer

























  • thanks a lot for your help Stephane Chazelas and @Kusalananda

    – Georgе Stoyanov
    Mar 11 at 9:20















2














To properly handle validation of an IP address or CIDR, use a library function specifically made for this, such as the cidrvalidate() Perl function in the Net::CIDR module:



$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/24
valid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/2
invalid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0
valid


See perldoc Net::CIDR for what else this library can do.



The -- are not necessary in the examples above but would be for arbitrary input from the user as otherwise, that input would be taken as an option by perl if it started with -.



The approaches below are variations on your attempt, which does not care about invalid netmasks.




A positive decimal integer between 0 and 255 may be matched by



[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]


A positive decimal integer between 0 and 32 may be matched by



[0-9]|[12][0-9]|3[012]


Using this:



#!/bin/bash

n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'

IFS= read -rp 'Input: ' ipaddr

if [[ $ipaddr =~ ^$n(.$n)3/$m$ ]]; then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


The expression



^$n(.$n)3/$m$


would expand to the full regular expression for a valid CIDR spanning the complete length of the given string.




The other obvious way to do this is to read the numbers in the given string and test whether the first four are in the 0-255 range and whether the fifth is in the range 0-32:



#!/bin/bash

IFS='./' read -rp 'Input: ' a b c d e

for var in "$a" "$b" "$c" "$d" "$e"; do
case $var in
""|*[!0123456789]*)
printf 'not a valid number: %sn' "$var"
exit 1
esac
done

ipaddr="$a.$b.$c.$d/$e"

if [ "$a" -ge 0 ] && [ "$a" -le 255 ] &&
[ "$b" -ge 0 ] && [ "$b" -le 255 ] &&
[ "$c" -ge 0 ] && [ "$c" -le 255 ] &&
[ "$d" -ge 0 ] && [ "$d" -le 255 ] &&
[ "$e" -ge 0 ] && [ "$e" -le 32 ]
then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


Here we read five words into five variables. The inputted string is split into words on . and / when read (which means 3/3/3/3.2 would be parsed as valid, but see $ipaddr in the code). Any non-integer data read would trigger the script to exit. We then start testing their values against the valid ranges. If any test fail, the address entered is not valid.






share|improve this answer

























  • thanks a lot for your help Stephane Chazelas and @Kusalananda

    – Georgе Stoyanov
    Mar 11 at 9:20













2












2








2







To properly handle validation of an IP address or CIDR, use a library function specifically made for this, such as the cidrvalidate() Perl function in the Net::CIDR module:



$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/24
valid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/2
invalid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0
valid


See perldoc Net::CIDR for what else this library can do.



The -- are not necessary in the examples above but would be for arbitrary input from the user as otherwise, that input would be taken as an option by perl if it started with -.



The approaches below are variations on your attempt, which does not care about invalid netmasks.




A positive decimal integer between 0 and 255 may be matched by



[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]


A positive decimal integer between 0 and 32 may be matched by



[0-9]|[12][0-9]|3[012]


Using this:



#!/bin/bash

n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'

IFS= read -rp 'Input: ' ipaddr

if [[ $ipaddr =~ ^$n(.$n)3/$m$ ]]; then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


The expression



^$n(.$n)3/$m$


would expand to the full regular expression for a valid CIDR spanning the complete length of the given string.




The other obvious way to do this is to read the numbers in the given string and test whether the first four are in the 0-255 range and whether the fifth is in the range 0-32:



#!/bin/bash

IFS='./' read -rp 'Input: ' a b c d e

for var in "$a" "$b" "$c" "$d" "$e"; do
case $var in
""|*[!0123456789]*)
printf 'not a valid number: %sn' "$var"
exit 1
esac
done

ipaddr="$a.$b.$c.$d/$e"

if [ "$a" -ge 0 ] && [ "$a" -le 255 ] &&
[ "$b" -ge 0 ] && [ "$b" -le 255 ] &&
[ "$c" -ge 0 ] && [ "$c" -le 255 ] &&
[ "$d" -ge 0 ] && [ "$d" -le 255 ] &&
[ "$e" -ge 0 ] && [ "$e" -le 32 ]
then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


Here we read five words into five variables. The inputted string is split into words on . and / when read (which means 3/3/3/3.2 would be parsed as valid, but see $ipaddr in the code). Any non-integer data read would trigger the script to exit. We then start testing their values against the valid ranges. If any test fail, the address entered is not valid.






share|improve this answer















To properly handle validation of an IP address or CIDR, use a library function specifically made for this, such as the cidrvalidate() Perl function in the Net::CIDR module:



$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/24
valid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/2
invalid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%sn", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0
valid


See perldoc Net::CIDR for what else this library can do.



The -- are not necessary in the examples above but would be for arbitrary input from the user as otherwise, that input would be taken as an option by perl if it started with -.



The approaches below are variations on your attempt, which does not care about invalid netmasks.




A positive decimal integer between 0 and 255 may be matched by



[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]


A positive decimal integer between 0 and 32 may be matched by



[0-9]|[12][0-9]|3[012]


Using this:



#!/bin/bash

n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'

IFS= read -rp 'Input: ' ipaddr

if [[ $ipaddr =~ ^$n(.$n)3/$m$ ]]; then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


The expression



^$n(.$n)3/$m$


would expand to the full regular expression for a valid CIDR spanning the complete length of the given string.




The other obvious way to do this is to read the numbers in the given string and test whether the first four are in the 0-255 range and whether the fifth is in the range 0-32:



#!/bin/bash

IFS='./' read -rp 'Input: ' a b c d e

for var in "$a" "$b" "$c" "$d" "$e"; do
case $var in
""|*[!0123456789]*)
printf 'not a valid number: %sn' "$var"
exit 1
esac
done

ipaddr="$a.$b.$c.$d/$e"

if [ "$a" -ge 0 ] && [ "$a" -le 255 ] &&
[ "$b" -ge 0 ] && [ "$b" -le 255 ] &&
[ "$c" -ge 0 ] && [ "$c" -le 255 ] &&
[ "$d" -ge 0 ] && [ "$d" -le 255 ] &&
[ "$e" -ge 0 ] && [ "$e" -le 32 ]
then
printf '"%s" is a valid CIDRn' "$ipaddr"
else
printf '"%s" is not validn' "$ipaddr"
fi


Here we read five words into five variables. The inputted string is split into words on . and / when read (which means 3/3/3/3.2 would be parsed as valid, but see $ipaddr in the code). Any non-integer data read would trigger the script to exit. We then start testing their values against the valid ranges. If any test fail, the address entered is not valid.







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 8 at 16:06









Stéphane Chazelas

313k57592948




313k57592948










answered Mar 8 at 12:06









KusalanandaKusalananda

140k17261434




140k17261434












  • thanks a lot for your help Stephane Chazelas and @Kusalananda

    – Georgе Stoyanov
    Mar 11 at 9:20

















  • thanks a lot for your help Stephane Chazelas and @Kusalananda

    – Georgе Stoyanov
    Mar 11 at 9:20
















thanks a lot for your help Stephane Chazelas and @Kusalananda

– Georgе Stoyanov
Mar 11 at 9:20





thanks a lot for your help Stephane Chazelas and @Kusalananda

– Georgе Stoyanov
Mar 11 at 9:20

















draft saved

draft discarded
















































Thanks for contributing an answer to Unix & Linux Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f505115%2fregex-expression-for-ip-address-cidr-in-bash%23new-answer', 'question_page');

);

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






Popular posts from this blog

How to check contact read email or not when send email to Individual?

Bahrain

Postfix configuration issue with fips on centos 7; mailgun relay