bash - for loop for IP range excluding certain IPs

15,410

Solution 1

Try this:

for ip in 10.11.{32..47}.{0..255}
do
        echo 10.11.{32..35}.{39..61} | grep -q "\<$ip\>" && continue
        echo "<ip>${ip}</ip>" 
done

This of course is a simple solution which still loops through the complete set and throws away some unwanted elements. As your comment suggests, this may produce unnecessary delays during the parts which are skipped. To avoid these, you can generate the values in parallel to the processing like this:

for ip in 10.11.{32..47}.{0..255}
do
        echo 10.11.{32..35}.{39..61} | grep -q "\<$ip\>" && continue
        echo "${ip}" 
done | while read ip
do
        process "$ip"
done

If the process "$ip" is taking at least a minimal amount of time, then the time for the generation of the values will most likely not fall into account anymore.

If you want to skip the values completely, you also can use a more complex term for your IPs (but then it will not be clear anymore how this code derived from the spec you gave in your question, so I better comment it thoroughly):

# ranges below result in
# 10.11.{32..47}.{0..255} without 10.11.{32..35}.{39..61}:
for ip in 10.11.{32..35}.{{0..38},{62..255}} 10.11.{36..47}.{0..255}
do
        echo "${ip}" 
done

Solution 2

Try this:

printf "%s\n" 10.11.{32..47}.{0..255} 10.11.{32..35}.{39..61} | sort | uniq -u | while read ip; do echo $ip; done
Share:
15,410
spacemtn5
Author by

spacemtn5

write code.

Updated on July 18, 2022

Comments

  • spacemtn5
    spacemtn5 almost 2 years

    I have the below for loop

    for ip in 10.11.{32..47}.{0..255}
    do
            echo "<ip>${ip}</ip>" 
    done
    

    I want to exclude this iprange: 10.11.{32..35}.{39..61} from the above for loop. This ip range is a subset of the above one. Is there a way to do that?

    I tried this, this doesn't work:

    abc=10.11.{34..37}.{39..61}
    for ip in 10.11.{32..47}.{0..255}
    do
        if [[ $ip == $abc ]]
        then
                echo "not_defined"
        else
                echo "<ip>${ip}</ip>"
        fi
    done
    
    • Etan Reisner
      Etan Reisner almost 9 years
      Are you asking if you can get the brace expansion to do that for you or are you asking how to write the logic in the loop to exclude those ranges?
  • Sato Katsura
    Sato Katsura almost 9 years
    Sadly this doesn't eliminate anything. You could try something like this instead: ... | sort | uniq -c | awk '$1 = 1 { print $2 }' | ...
  • Cyrus
    Cyrus almost 9 years
    @SatoKatsura: Can't reproduce this with bash version 4.3.11. printf create 4188 lines and | sort | uniq -u reduce it to 4004 lines.
  • spacemtn5
    spacemtn5 almost 9 years
    This is great Alfe, but we are still looping thru the ip range 10.11.{32..35}.{39..61} (which we wanted to exclude) but not printing the output. Please correct me if I am wrong. I was planning on adding an "if condition" inside the "for loop" to exclude the ip range 10.11.{32..35}.{39..61}. I have a bunch of other commands to be included inside the for loop, not just echo. I'm planning to save time by not hitting this ip-range, just not printing the output will not help.
  • Alfe
    Alfe almost 9 years
    Normally whatever you do in these loops will take much more time than the looping itself, but I see your point and will do my best to address this. Stay tuned.
  • Alfe
    Alfe almost 9 years
    Added some more versions.
  • spacemtn5
    spacemtn5 almost 9 years
    Alfe, Thank you sir. This looks great but you mentioned that the origin will not be visible anymore. Which origin are you talking about?
  • Alfe
    Alfe almost 9 years
    You are right, this was unclear. I rephrased the answer there to explain in more detail and more clearly what I mean.
  • Alfe
    Alfe almost 9 years
    Didn't know the option -u for uniq yet. Thanks for that hint!
  • spacemtn5
    spacemtn5 almost 9 years
    Cyrus, Your solution is awesome too. Just modified yours at the sort, that would have been perfect. printf "%s\n" 10.11.{32..47}.{0..255} 10.11.{32..35}.{39..61} | sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n | uniq -u | while read ip; do echo $ip; done
  • Cyrus
    Cyrus almost 9 years
    @spacemtn5: Thank you for this hint.