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

后端 未结 20 1867
予麋鹿
予麋鹿 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:54

    The POSIX way

    If you care about portability, use the example from the POSIX standard:

    i=2
    end=5
    while [ $i -le $end ]; do
        echo $i
        i=$(($i+1))
    done
    

    Output:

    2
    3
    4
    5
    

    Things which are not POSIX:

    • (( )) without dollar, although it is a common extension as mentioned by POSIX itself.
    • [[. [ is enough here. See also: What is the difference between single and double square brackets in Bash?
    • for ((;;))
    • seq (GNU Coreutils)
    • {start..end}, and that cannot work with variables as mentioned by the Bash manual.
    • let i=i+1: POSIX 7 2. Shell Command Language does not contain the word let, and it fails on bash --posix 4.3.42
    • the dollar at i=$i+1 might be required, but I'm not sure. POSIX 7 2.6.4 Arithmetic Expansion says:

      If the shell variable x contains a value that forms a valid integer constant, optionally including a leading plus or minus sign, then the arithmetic expansions "$((x))" and "$(($x))" shall return the same value.

      but reading it literally that does not imply that $((x+1)) expands since x+1 is not a variable.

    0 讨论(0)
  • 2020-11-21 05:56

    The seq method is the simplest, but Bash has built-in arithmetic evaluation.

    END=5
    for ((i=1;i<=END;i++)); do
        echo $i
    done
    # ==> outputs 1 2 3 4 5 on separate lines
    

    The for ((expr1;expr2;expr3)); construct works just like for (expr1;expr2;expr3) in C and similar languages, and like other ((expr)) cases, Bash treats them as arithmetic.

    0 讨论(0)
  • 2020-11-21 05:57

    If you're doing shell commands and you (like I) have a fetish for pipelining, this one is good:

    seq 1 $END | xargs -I {} echo {}

    0 讨论(0)
  • 2020-11-21 05:58

    Another layer of indirection:

    for i in $(eval echo {1..$END}); do
        ∶
    
    0 讨论(0)
  • 2020-11-21 06:03

    If you need it prefix than you might like this

     for ((i=7;i<=12;i++)); do echo `printf "%2.0d\n" $i |sed "s/ /0/"`;done
    

    that will yield

    07
    08
    09
    10
    11
    12
    
    0 讨论(0)
  • 2020-11-21 06:03

    I know this question is about bash, but - just for the record - ksh93 is smarter and implements it as expected:

    $ ksh -c 'i=5; for x in {1..$i}; do echo "$x"; done'
    1
    2
    3
    4
    5
    $ ksh -c 'echo $KSH_VERSION'
    Version JM 93u+ 2012-02-29
    
    $ bash -c 'i=5; for x in {1..$i}; do echo "$x"; done'
    {1..5}
    
    0 讨论(0)
提交回复
热议问题