How do I iterate over a range of numbers defined by variables in Bash?

后端 未结 20 1892
予麋鹿
予麋鹿 2020-11-21 05:19

How do I iterate over a range of numbers in Bash when the range is given by a variable?

I know I can do this (called \"sequence expression\" in the Bash documentatio

20条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-21 05:41

    I've combined a few of the ideas here and measured performance.

    TL;DR Takeaways:

    1. seq and {..} are really fast
    2. for and while loops are slow
    3. $( ) is slow
    4. for (( ; ; )) loops are slower
    5. $(( )) is even slower
    6. Worrying about N numbers in memory (seq or {..}) is silly (at least up to 1 million.)

    These are not conclusions. You would have to look at the C code behind each of these to draw conclusions. This is more about how we tend to use each of these mechanisms for looping over code. Most single operations are close enough to being the same speed that it's not going to matter in most cases. But a mechanism like for (( i=1; i<=1000000; i++ )) is many operations as you can visually see. It is also many more operations per loop than you get from for i in $(seq 1 1000000). And that may not be obvious to you, which is why doing tests like this is valuable.

    Demos

    # show that seq is fast
    $ time (seq 1 1000000 | wc)
     1000000 1000000 6888894
    
    real    0m0.227s
    user    0m0.239s
    sys     0m0.008s
    
    # show that {..} is fast
    $ time (echo {1..1000000} | wc)
           1 1000000 6888896
    
    real    0m1.778s
    user    0m1.735s
    sys     0m0.072s
    
    # Show that for loops (even with a : noop) are slow
    $ time (for i in {1..1000000} ; do :; done | wc)
           0       0       0
    
    real    0m3.642s
    user    0m3.582s
    sys 0m0.057s
    
    # show that echo is slow
    $ time (for i in {1..1000000} ; do echo $i; done | wc)
     1000000 1000000 6888896
    
    real    0m7.480s
    user    0m6.803s
    sys     0m2.580s
    
    $ time (for i in $(seq 1 1000000) ; do echo $i; done | wc)
     1000000 1000000 6888894
    
    real    0m7.029s
    user    0m6.335s
    sys     0m2.666s
    
    # show that C-style for loops are slower
    $ time (for (( i=1; i<=1000000; i++ )) ; do echo $i; done | wc)
     1000000 1000000 6888896
    
    real    0m12.391s
    user    0m11.069s
    sys     0m3.437s
    
    # show that arithmetic expansion is even slower
    $ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; i=$(($i+1)); done | wc)
     1000000 1000000 6888896
    
    real    0m19.696s
    user    0m18.017s
    sys     0m3.806s
    
    $ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; ((i=i+1)); done | wc)
     1000000 1000000 6888896
    
    real    0m18.629s
    user    0m16.843s
    sys     0m3.936s
    
    $ time (i=1; e=1000000; while [ $i -le $e ]; do echo $((i++)); done | wc)
     1000000 1000000 6888896
    
    real    0m17.012s
    user    0m15.319s
    sys     0m3.906s
    
    # even a noop is slow
    $ time (i=1; e=1000000; while [ $((i++)) -le $e ]; do :; done | wc)
           0       0       0
    
    real    0m12.679s
    user    0m11.658s
    sys 0m1.004s
    

提交回复
热议问题