Bash脚本列出前缀中的所有IP

use*_*938 13 bash ip-address

我试图创建脚本,我可以输入一组前缀,然后将列出的前缀(包括网络/主机/广播)内的所有IP地址.

一个例子是:

./convert-prefix-to-IPs.sh 192.168.0.0/23 203.20.0.0/16
192.168.0.0
192.168.0.1
... 
192.168.0.255
192.168.1.0
.. 
192.168.1.255
203.20.0.0
..
203.20.255.255
Run Code Online (Sandbox Code Playgroud)

有一些Python/Perl脚本可以做到这一点,但我希望能有一个简单的bash脚本,因为它可能会在没有的Perl/Python的系统中使用(是的..我知道..)

小智 25

这是我用来生成给定CIDR块中的所有IP地址的内容

nmap -sL 10.10.64.0/27 | awk '/Nmap scan report/{print $NF}'
Run Code Online (Sandbox Code Playgroud)

就这么简单

上面的命令输出这个

10.10.64.0
10.10.64.1
10.10.64.2
10.10.64.3
10.10.64.4
10.10.64.5
10.10.64.6
10.10.64.7
10.10.64.8
10.10.64.9
10.10.64.10
10.10.64.11
10.10.64.12
10.10.64.13
10.10.64.14
10.10.64.15
10.10.64.16
10.10.64.17
10.10.64.18
10.10.64.19
10.10.64.20
10.10.64.21
10.10.64.22
10.10.64.23
10.10.64.24
10.10.64.25
10.10.64.26
10.10.64.27
10.10.64.28
10.10.64.29
10.10.64.30
10.10.64.31
Run Code Online (Sandbox Code Playgroud)

  • 为什么这个答案没有被标记为正确?这太有用了。 (2认同)
  • 美丽.我将添加一个更正:`nmap -n -sL 10.10.64.0/27`以避免反向DNS查找,这会使用几行(例如`(10.10.64.30)`)破坏输出. (2认同)

小智 17

我也在寻找这个解决方案,发现@scherand脚本效果很好.我也添加了这个脚本,为您提供更多选择.帮助文件如下.

这篇文章将扩大CIDR地址.

概要

./cidr-to-ip.sh [OPTION(only one)] [STRING/FILENAME]
Run Code Online (Sandbox Code Playgroud)

描述

-h显示此帮助屏幕

-f在给定STRING(s)时强制检查网络边界

-i将从输入文件中读取(文件每行应包含一个CIDR)(无网络边界检查)

-b将与-i相同但使用网络边界检查

例子

./cidr-to-ip.sh 192.168.0.1/24

./cidr-to-ip.sh 192.168.0.1/24 10.10.0.0/28

./cidr-to-ip.sh -f 192.168.0.0/16

./cidr-to-ip.sh -i inputfile.txt

./cidr-to-ip.sh -b inputfile.txt

#!/bin/bash    

############################
##  Methods
############################   
prefix_to_bit_netmask() {
    prefix=$1;
    shift=$(( 32 - prefix ));

    bitmask=""
    for (( i=0; i < 32; i++ )); do
        num=0
        if [ $i -lt $prefix ]; then
            num=1
        fi

        space=
        if [ $(( i % 8 )) -eq 0 ]; then
            space=" ";
        fi

        bitmask="${bitmask}${space}${num}"
    done
    echo $bitmask
}

bit_netmask_to_wildcard_netmask() {
    bitmask=$1;
    wildcard_mask=
    for octet in $bitmask; do
        wildcard_mask="${wildcard_mask} $(( 255 - 2#$octet ))"
    done
    echo $wildcard_mask;
}

check_net_boundary() {
    net=$1;
    wildcard_mask=$2;
    is_correct=1;
    for (( i = 1; i <= 4; i++ )); do
        net_octet=$(echo $net | cut -d '.' -f $i)
        mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
        if [ $mask_octet -gt 0 ]; then
            if [ $(( $net_octet&$mask_octet )) -ne 0 ]; then
                is_correct=0;
            fi
        fi
    done
    echo $is_correct;
}

#######################
##  MAIN
#######################
OPTIND=1;
getopts "fibh" force;

shift $((OPTIND-1))
if [ $force = 'h' ]; then
    echo ""
    echo -e "THIS SCRIPT WILL EXPAND A CIDR ADDRESS.\n\nSYNOPSIS\n  ./cidr-to-ip.sh [OPTION(only one)] [STRING/FILENAME]\nDESCRIPTION\n -h  Displays this help screen\n -f  Forces a check for network boundary when given a STRING(s)\n    -i  Will read from an Input file (no network boundary check)\n  -b  Will do the same as –i but with network boundary check\n\nEXAMPLES\n    ./cidr-to-ip.sh  192.168.0.1/24\n   ./cidr-to-ip.sh  192.168.0.1/24 10.10.0.0/28\n  ./cidr-to-ip.sh  -f 192.168.0.0/16\n    ./cidr-to-ip.sh  -i inputfile.txt\n ./cidr-to-ip.sh  -b inputfile.txt\n"
    exit
fi

if [ $force = 'i' ] || [ $force = 'b' ]; then

    old_IPS=$IPS
    IPS=$'\n'
    lines=($(cat $1)) # array
    IPS=$old_IPS
        else
            lines=$@
fi

for ip in ${lines[@]}; do
    net=$(echo $ip | cut -d '/' -f 1);
    prefix=$(echo $ip | cut -d '/' -f 2);
    do_processing=1;

    bit_netmask=$(prefix_to_bit_netmask $prefix);

    wildcard_mask=$(bit_netmask_to_wildcard_netmask "$bit_netmask");
    is_net_boundary=$(check_net_boundary $net "$wildcard_mask");

    if [ $force = 'f' ] && [ $is_net_boundary -ne 1 ] || [ $force = 'b' ] && [ $is_net_boundary -ne 1 ] ; then
        read -p "Not a network boundary! Continue anyway (y/N)? " -n 1 -r
        echo    ## move to a new line
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            do_processing=1;
        else
            do_processing=0;
        fi
    fi  

    if [ $do_processing -eq 1 ]; then
        str=
        for (( i = 1; i <= 4; i++ )); do
            range=$(echo $net | cut -d '.' -f $i)
            mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
            if [ $mask_octet -gt 0 ]; then
                range="{$range..$(( $range | $mask_octet ))}";
            fi
            str="${str} $range"
        done
        ips=$(echo $str | sed "s, ,\\.,g"); ## replace spaces with periods, a join...

        eval echo $ips | tr ' ' '\n'
else
exit
    fi

done
Run Code Online (Sandbox Code Playgroud)


Flo*_*aus 7

我最近编写了一个函数来从给定的网络地址生成所有 IP 地址。该函数将网络地址作为参数并接受 CIDR 和子网掩码。然后脚本将所有 IP 存储在数组变量 $ips 中。

代码

network_address_to_ips() {
  # create array containing network address and subnet
  local network=(${1//\// })
  # split network address by dot
  local iparr=(${network[0]//./ })
  # if no mask given it's the same as /32
  local mask=32
  [[ $((${#network[@]})) -gt 1 ]] && mask=${network[1]}

  # convert dot-notation subnet mask or convert CIDR to an array like (255 255 255 0)
  local maskarr
  if [[ ${mask} =~ '.' ]]; then  # already mask format like 255.255.255.0
    maskarr=(${mask//./ })
  else                           # assume CIDR like /24, convert to mask
    if [[ $((mask)) -lt 8 ]]; then
      maskarr=($((256-2**(8-mask))) 0 0 0)
    elif  [[ $((mask)) -lt 16 ]]; then
      maskarr=(255 $((256-2**(16-mask))) 0 0)
    elif  [[ $((mask)) -lt 24 ]]; then
      maskarr=(255 255 $((256-2**(24-mask))) 0)
    elif [[ $((mask)) -lt 32 ]]; then
      maskarr=(255 255 255 $((256-2**(32-mask))))
    elif [[ ${mask} == 32 ]]; then
      maskarr=(255 255 255 255)
    fi
  fi

  # correct wrong subnet masks (e.g. 240.192.255.0 to 255.255.255.0)
  [[ ${maskarr[2]} == 255 ]] && maskarr[1]=255
  [[ ${maskarr[1]} == 255 ]] && maskarr[0]=255

  # generate list of ip addresses
  local bytes=(0 0 0 0)
  for i in $(seq 0 $((255-maskarr[0]))); do
    bytes[0]="$(( i+(iparr[0] & maskarr[0]) ))"
    for j in $(seq 0 $((255-maskarr[1]))); do
      bytes[1]="$(( j+(iparr[1] & maskarr[1]) ))"
      for k in $(seq 0 $((255-maskarr[2]))); do
        bytes[2]="$(( k+(iparr[2] & maskarr[2]) ))"
        for l in $(seq 1 $((255-maskarr[3]))); do
          bytes[3]="$(( l+(iparr[3] & maskarr[3]) ))"
          printf "%d.%d.%d.%d\n" "${bytes[@]}"
        done
      done
    done
  done
}
Run Code Online (Sandbox Code Playgroud)

例子

network_address_to_ips 10.0.1.0/255.255.255.240
network_address_to_ips 10.1.0.0/24
Run Code Online (Sandbox Code Playgroud)


Ale*_*vey 7

此简短脚本将在几行Bash中打印CIDR范围内的所有IP地址。(我以相同名称pripsUbuntu命令命名。显然,如果该命令可用,请使用该命令。)

prips() {
  local cidr=$1 ; local lo hi a b c d e f g h

  # range is bounded by network (-n) & broadcast (-b) addresses.
  lo=$(ipcalc -n "$cidr" | cut -f2 -d=)
  hi=$(ipcalc -b "$cidr" | cut -f2 -d=)

  IFS=. read -r a b c d <<< "$lo"
  IFS=. read -r e f g h <<< "$hi"

  eval "echo {$a..$e}.{$b..$f}.{$c..$g}.{$d..$h}"
}
Run Code Online (Sandbox Code Playgroud)

请注意,我假设使用RedHat Linux(Erik Troan,Preston Brown)版本ipcalc,而不是某些平台(例如Mac OS X)上安装的Krischan Jodies版本。

例子:

$ prips 10.0.0.128/27
10.0.0.128 10.0.0.129 10.0.0.130 10.0.0.131 10.0.0.132 10.0.0.133 10.0.0.134 10.0.0.135 10.0.0.136 10.0.0.137 10.0.0.138 10.0.0.139 10.0.0.140 10.0.0.141 10.0.0.142 10.0.0.143 10.0.0.144 10.0.0.145 10.0.0.146 10.0.0.147 10.0.0.148 10.0.0.149 10.0.0.150 10.0.0.151 10.0.0.152 10.0.0.153 10.0.0.154 10.0.0.155 10.0.0.156 10.0.0.157 10.0.0.158 10.0.0.159
Run Code Online (Sandbox Code Playgroud)

计算/ 23网络中的正确地址数:

$ prips 10.0.0.0/23 | wc -w 
512
Run Code Online (Sandbox Code Playgroud)

使用cut检查其中一些地址:

$ prips 10.0.0.0/23 | cut -f1-10,256-266 -d' '
10.0.0.0 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.9 10.0.0.255 10.0.1.0 10.0.1.1 10.0.1.2 10.0.1.3 10.0.1.4 10.0.1.5 10.0.1.6 10.0.1.7 10.0.1.8 10.0.1.9
Run Code Online (Sandbox Code Playgroud)

可能速度太慢,但也无法在/ 8网络中正确生成1600万个地址:

$ date ; prips 10.0.0.0/8 | wc -w ; date 
Sat May 20 18:06:00 AEST 2017
16777216
Sat May 20 18:06:41 AEST 2017
Run Code Online (Sandbox Code Playgroud)


小智 7

这个脚本应该可以。它(几乎)是纯粹的 Bash。seq如果需要完全纯粹的 bash,可以更换该部分。

由于 Bash 显然使用带符号的二补码 4 字节整数,因此该脚本限制为 /8 掩码最大值。我发现大于 /16 的范围无论如何都是不切实际的,所以这根本不会困扰我。如果有人知道克服这个问题的简单方法,请分享:)

#!/usr/bin/env bash

BASE_IP=${1%/*}
IP_CIDR=${1#*/}

if [ ${IP_CIDR} -lt 8 ]; then
    echo "Max range is /8."
    exit
fi

IP_MASK=$((0xFFFFFFFF << (32 - ${IP_CIDR})))

IFS=. read a b c d <<<${BASE_IP}

ip=$((($b << 16) + ($c << 8) + $d))

ipstart=$((${ip} & ${IP_MASK}))
ipend=$(((${ipstart} | ~${IP_MASK}) & 0x7FFFFFFF))

seq ${ipstart} ${ipend} | while read i; do
    echo $a.$((($i & 0xFF0000) >> 16)).$((($i & 0xFF00) >> 8)).$(($i & 0x00FF))
done
Run Code Online (Sandbox Code Playgroud)

用法:

./script.sh 192.168.13.55/22
Run Code Online (Sandbox Code Playgroud)

使用 Bash 版本 4.4.23 进行测试。YMMV。


Jak*_*ski 6

nmap 是有用的,但是太过分了。

您可以prips改用。为您省去了从nmap并使用的额外输出的麻烦awk

呼叫prips 192.168.0.0/23将打印您需要的内容。

我使用以下命令跳过网络地址并广播: prips "$subnet" | sed -e '1d; $d'

Prips还具有其他有用的选项,例如能够对每个第n个IP进行采样。

这是通过使用aptbrewrpmtar.gz

  • 请参阅类似的:[`cidrl`](https://github.com/emden-norfolk/cidrl),它也适用于 IPv6。 (2认同)

小智 2

我认为我编写的这个小脚本可以达到目的。如果没有,这绝对是一个起点!祝你好运。

#!/bin/bash                                                                                                                                                                                                                                                              

############################                                                                                                                                                                                                                                             
##  Methods                                                                                                                                                                                                                                                              
############################                                                                                                                                                                                                                                             
prefix_to_bit_netmask() {
    prefix=$1;
    shift=$(( 32 - prefix ));

    bitmask=""
    for (( i=0; i < 32; i++ )); do
        num=0
        if [ $i -lt $prefix ]; then
            num=1
        fi

        space=
        if [ $(( i % 8 )) -eq 0 ]; then
            space=" ";
        fi

        bitmask="${bitmask}${space}${num}"
    done
    echo $bitmask
}

bit_netmask_to_wildcard_netmask() {
    bitmask=$1;
    wildcard_mask=
    for octet in $bitmask; do
        wildcard_mask="${wildcard_mask} $(( 255 - 2#$octet ))"
    done
    echo $wildcard_mask;
}



#######################                                                                                                                                                                                                                                                  
##  MAIN                                                                                                                                                                                                                                                                 
#######################                                                                                                                                                                                                                                                  
for ip in $@; do
    net=$(echo $ip | cut -d '/' -f 1);
    prefix=$(echo $ip | cut -d '/' -f 2);

    bit_netmask=$(prefix_to_bit_netmask $prefix);

    wildcard_mask=$(bit_netmask_to_wildcard_netmask "$bit_netmask");

    str=
    for (( i = 1; i <= 4; i++ )); do
        range=$(echo $net | cut -d '.' -f $i)
        mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
        if [ $mask_octet -gt 0 ]; then
            range="{0..$mask_octet}";
        fi
        str="${str} $range"
    done
    ips=$(echo $str | sed "s, ,\\.,g"); ## replace spaces with periods, a join...                                                                                                                                                                                        
    eval echo $ips | tr ' ' '\012'

done
Run Code Online (Sandbox Code Playgroud)