2013-03-15 16 views
13

In uno script bash ho un indirizzo IP come 192.168.1.15 e una maschera di rete come 255.255.0.0. Ora voglio calcolare l'indirizzo iniziale di questa rete, ovvero utilizzare il & -operator su entrambi gli indirizzi. Nell'esempio, il risultato sarebbe 192.168.0.0. Qualcuno ha qualcosa di simile pronto? Sto cercando un modo elegante per trattare con gli indirizzi IP da bashDato l'IP e la maschera di rete, come posso calcolare l'indirizzo di rete usando bash?

+2

si può considerare 'ipcalc'. – dwalter

+0

ipcalc è uno script perl cgi che può essere scaricato. Grazie, è un'ottima fonte per chiunque voglia implementarlo in PERL. Tuttavia, stavo cercando una soluzione in bash, ma perl avrebbe funzionato anche in uno script di shell. – Christian

+1

no intendo la riga di comando di Unix su ipcalc. vedi http://answers.oreilly.com/topic/411-how-to-calculate-subnets-with-ipcalc/ per ulteriori informazioni. In alternativa puoi anche usare sipcalc (anche uno strumento cli) che supporta IPv6 – dwalter

risposta

31

Usa bit a bit & (AND) Operatore:

$ IFS=. read -r i1 i2 i3 i4 <<< "192.168.1.15" 
$ IFS=. read -r m1 m2 m3 m4 <<< "255.255.0.0" 
$ printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))" 
192.168.0.0 

Esempio con un altro IP e la maschera:

$ IFS=. read -r i1 i2 i3 i4 <<< "10.0.14.97" 
$ IFS=. read -r m1 m2 m3 m4 <<< "255.255.255.248" 
$ printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))" 
10.0.14.96 
+1

Grazie mille! Esattamente quello che stavo cercando, bellissimo! – Christian

+0

Questo è geniale. Grazie per aver dedicato del tempo per svilupparlo. – jacksonecac

2

Grande risposta , anche se errore di battitura in risposta sopra.

$ printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$(($i2 <-- $i2 should be i2 

se qualcuno sa come calcolare l'indirizzo di broadcast (XOR rete), quindi calcolare i nodi utilizzabili tra rete e broadcast Sarei interessato in quei passi successivi. Devo trovare gli indirizzi in una lista all'interno di un/23.

+0

Risolto il problema, grazie per averlo notato. – kamituel

3

Solo l'aggiunta di un'alternativa se avete il prefisso solo rete disponibile (senza maschera di rete):

IP=10.20.30.240 
PREFIX=26 
IFS=. read -r i1 i2 i3 i4 <<< $IP 
IFS=. read -r xx m1 m2 m3 m4 <<< $(for a in $(seq 1 32); do if [ $(((a - 1) % 8)) -eq 0 ]; then echo -n .; fi; if [ $a -le $PREFIX ]; then echo -n 1; else echo -n 0; fi; done) 
printf "%d.%d.%d.%d\n" "$((i1 & (2#$m1)))" "$((i2 & (2#$m2)))" "$((i3 & (2#$m3)))" "$((i4 & (2#$m4)))" 
10

Alcune funzioni Bash che riassumono tutte le altre risposte.

ip2int() 
{ 
    local a b c d 
    { IFS=. read a b c d; } <<< $1 
    echo $(((((((a << 8) | b) << 8) | c) << 8) | d)) 
} 

int2ip() 
{ 
    local ui32=$1; shift 
    local ip n 
    for n in 1 2 3 4; do 
     ip=$((ui32 & 0xff))${ip:+.}$ip 
     ui32=$((ui32 >> 8)) 
    done 
    echo $ip 
} 

netmask() 
{ 
    local mask=$((0xffffffff << (32 - $1))); shift 
    int2ip $mask 
} 


broadcast() 
{ 
    local addr=$(ip2int $1); shift 
    local mask=$((0xffffffff << (32 -$1))); shift 
    int2ip $((addr | ~mask)) 
} 

network() 
{ 
    local addr=$(ip2int $1); shift 
    local mask=$((0xffffffff << (32 -$1))); shift 
    int2ip $((addr & mask)) 
} 
+4

Bello, ma una riga di esempio mi avrebbe risparmiato 15 minuti per capire le tue aspettative sui parametri .. "network 192.168.8.1 31" o "netmask 16" –

0

Oltre a rispondere a @Janci

IP=10.20.30.240 
PREFIX=26 
IFS=. read -r i1 i2 i3 i4 <<< $IP 
D2B=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}) 
binIP=${D2B[$i1]}${D2B[$i2]}${D2B[$i3]}${D2B[$i4]} 
binIP0=${binIP::$PREFIX}$(printf '0%.0s' $(seq 1 $((32-$PREFIX)))) 
# binIP1=${binIP::$PREFIX}$(printf '0%.0s' $(seq 1 $((31-$PREFIX))))1 
echo $((2#${binIP0::8})).$((2#${binIP0:8:8})).$((2#${binIP0:16:8})).$((2#${binIP0:24:8})) 
Problemi correlati