На баше как-то так (минимум внешних команд, от cat можно избавиться, если использовать exec):
#!/bin/bash
octets=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
addrtobin(){
for digit in ${1//./ }; do echo -n ${octets[digit]}; done
}
# Просто пример для списков адресов и сетей.
# Лучше используйте exec N<>filename.txt + read -u N
ips=$(cat ips.txt)
nets=$(cat nets.txt)
for ip in $ips
do
out=1
bin_ip=$(addrtobin $ip)
for net in $nets
do
bin_net=$(addrtobin ${net%%/*})
net_mask=${net#*/}
if [ "${bin_ip:1:$net_mask}" == "${bin_net:1:$net_mask}" ]
then
out=0
break # Чтобы не проходить до конца списка сетей, если адрес уже найден
fi
done
[ $out -eq 1 ] && echo $ip
done
К сожалению, придется делать двойной цикл. К счастью, можно не прогонять внутренний цикл до конца, если совпадение найдено, поэтому будет самую малость быстрее.