Reputation: 321
I'm trying to make a case statement and i am using the following wildcards to make the diff between the arguments:
This is for a single IP:
case $1 in
//the argument is a single IP
*.*.*.0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31`|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255 )
....`
//the argument is a IP range
`*.*.*.*-*.*.*.* )
....`
Even so, it seems that its not working, what am I doing wrong?
thanks,
Upvotes: 0
Views: 379
Reputation: 46813
Maybe this little loop can help you:
#!/bin/bash
shopt -s extglob
is_a_byte() {
local i
for i do
[[ "$i" = +([[:digit:]]) ]] && ((10#$i<=255)) || return 1
done
}
is_ip() {
local ipn
read -a ipn <<< "${1//./ }"
if [[ "${#ipn[@]}" = 4 ]] && is_a_byte "${ipn[@]}"; then
[[ "$2" ]] && printf -v "$2" "%s" $(( ((((((10#${ipn[0]}<<8)|10#${ipn[1]})<<8)|10#${ipn[2]})<<8)|10#${ipn[3]}) ))
return 0
else
return 1
fi
}
while IFS=- read -e -r -p "Enter an IP or an IP range: " -a ip; do
if [[ -z ${ip[1]} ]]; then
if is_ip "${ip[0]}" N; then
echo "Valid IP ---> $N"
else
echo "${ip[0]} is not a valid IP"
fi
else
if is_ip "${ip[0]}" N[0] && is_ip "${ip[1]}" N[1]; then
((N[0]>N[1])) && N=( "${N[1]}" "${N[0]}" )
echo "Valid IP range ---> ${N[0]}-${N[1]}"
else
echo "${ip[0]}-${ip[1]} is not a valid IP range"
fi
fi
done
No grep, no subshell, only pure bash, and it is much more robust than a clumsy glob/regex, and I would say it's rather elegant ;-)
.
Upvotes: 1
Reputation: 74018
For the single IP, you have defined these alternatives
*.*.*.0
1
2
and not
*.*.*.0
*.*.*.1
*.*.*.2
The pattern type used here is called glob
.
If you really want to spell it out, you have to say
*.*.*.0|*.*.*.1|*.*.*.2|...)
When you want to have at most three characters, you can specify this as well
*.*.*.?|*.*.*.??|*.*.*.???)
or with at most three digits
*.*.*.[0-9]|*.*.*.[0-9][0-9]|*.*.*.[0-9][0-9][0-9])
but this allows e.g. 127.1.3.843
as well.
If you have
case "$arg" in
single-IP) ... ;;
IP-range) ... ;;
esac
it will first test single-IP, which always matches. To match ranges as well, you must list the pattern for the IP range first
case "$arg" in
IP-range) ... ;;
single-IP) ... ;;
esac
then it tests the IP range case first, and only if it doesn't match tests for the single IP pattern.
For a simplified test, see
case "$1" in
*.*.*.*-*.*.*.*) echo range ;;
*.*.*.*) echo single ;;
*) echo else ;;
esac
this gives
$ sh /tmp/a.sh 1.2.3.4
single
$ sh /tmp/a.sh 1.2.3.4-5.6.7.8
range
$ sh /tmp/a.sh 1.2.3
else
Upvotes: 4