2013-03-15 58 views
13

Trong tập lệnh bash, tôi có địa chỉ IP như 192.168.1.15 và mặt nạ mạng như 255.255.0.0. Bây giờ tôi muốn tính địa chỉ bắt đầu của mạng này, điều đó có nghĩa là sử dụng & -operator trên cả hai địa chỉ. Trong ví dụ này, kết quả sẽ là 192.168.0.0. Có ai đó có cái gì đó như thế này chưa? Tôi đang tìm kiếm một cách thanh lịch để đối phó với các địa chỉ ip từ bashVới IP và mặt nạ mạng, làm thế nào tôi có thể tính địa chỉ mạng bằng bash?

+2

Bạn có thể xem xét 'ipcalc'. – dwalter

+0

ipcalc là tập lệnh perl cgi có thể tải xuống. Cảm ơn, đó là một nguồn tuyệt vời cho bất cứ ai muốn thực hiện nó trong PERL. Tôi đã tìm kiếm một giải pháp trong bash mặc dù, nhưng perl sẽ làm việc trong một kịch bản shell, quá. – Christian

+1

không có nghĩa là dòng lệnh unix đến ipcalc. xem http://answers.oreilly.com/topic/411-how-to-calculate-subnets-with-ipcalc/ để biết thêm thông tin. Thay vào đó bạn cũng có thể sử dụng sipcalc (cũng là một công cụ cli) hỗ trợ IPv6 – dwalter

Trả lời

31

Sử dụng Bitwise & (AND) điều hành:

$ 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 

Ví dụ với một IP và mặt nạ:

$ 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

Cảm ơn bạn rất nhiều! Chính xác những gì tôi đang tìm kiếm, đẹp! – Christian

+0

Điều này thật tuyệt vời. Cảm ơn bạn đã dành thời gian để phát triển nó. – jacksonecac

2

Great câu trả lời , mặc dù typo nhỏ trong câu trả lời ở trên.

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

Nếu có ai biết cách tính địa chỉ quảng bá (XOR mạng), thì hãy tính toán các nút có thể sử dụng giữa mạng và chương trình phát sóng. Tôi phải tìm địa chỉ trong một danh sách trong một/23.

+0

Cố định câu trả lời, cảm ơn vì đã chú ý. – kamituel

3

Chỉ cần thêm một sự thay thế nếu bạn chỉ có mạng tiền tố có sẵn (không netmask):

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

Một số chức năng Bash tóm tắt tất cả câu trả lời khác.

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

Tốt nhưng một dòng ví dụ sẽ tiết kiệm cho tôi 15 phút để tìm ra các kỳ vọng tham số của bạn .. "mạng 192.168.8.1 31" hoặc "mặt nạ mạng 16" –

0

Ngoài @Janci trả lời

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})) 
Các vấn đề liên quan