0

我正在尝试做一个案例陈述,并且我正在使用以下通配符来区分参数之间的差异:

这是针对单个 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

    `*.*.*.*-*.*.*.* )

    ....`

即使这样,它似乎也不起作用,我做错了什么?

谢谢,

4

2 回答 2

4

对于单个 IP,您已经定义了这些替代方案

  • *.*.*.0
  • 1
  • 2
  • ...

不是

  • *.*.*.0
  • *.*.*.1
  • *.*.*.2
  • ...

此处使用的模式类型称为glob.

如果你真的想把它拼出来,你必须说

*.*.*.0|*.*.*.1|*.*.*.2|...)

当您希望最多包含三个字符时,您也可以指定它

*.*.*.?|*.*.*.??|*.*.*.???)

或最多三位数字

*.*.*.[0-9]|*.*.*.[0-9][0-9]|*.*.*.[0-9][0-9][0-9])

但这127.1.3.843也允许。

如果你有

case "$arg" in
single-IP) ... ;;
IP-range) ... ;;
esac

它将首先测试始终匹配的单 IP。要同时匹配范围,您必须首先列出 IP 范围的模式

case "$arg" in
IP-range) ... ;;
single-IP) ... ;;
esac

然后它首先测试 IP 范围的情况,并且仅当它与单个 IP 模式的测试不匹配时。

有关简化测试,请参阅

case "$1" in
*.*.*.*-*.*.*.*) echo range ;;
*.*.*.*) echo single ;;
*) echo else ;;
esac

这给了

$ 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
于 2012-12-31T14:04:19.667 回答
1

也许这个小循环可以帮助你:

#!/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

没有 grep,没有 subshel​​l,只有纯 bash,而且它比笨拙的 glob/regex 更健壮,我会说它相当优雅;-)

于 2012-12-31T15:01:47.573 回答