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

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

    discussion

    Using seq is fine, as Jiaaro suggested. Pax Diablo suggested a Bash loop to avoid calling a subprocess, with the additional advantage of being more memory friendly if $END is too large. Zathrus spotted a typical bug in the loop implementation, and also hinted that since i is a text variable, continuous conversions to-and-fro numbers are performed with an associated slow-down.

    integer arithmetic

    This is an improved version of the Bash loop:

    typeset -i i END
    let END=5 i=1
    while ((i<=END)); do
        echo $i
        …
        let i++
    done
    

    If the only thing that we want is the echo, then we could write echo $((i++)).

    ephemient taught me something: Bash allows for ((expr;expr;expr)) constructs. Since I've never read the whole man page for Bash (like I've done with the Korn shell (ksh) man page, and that was a long time ago), I missed that.

    So,

    typeset -i i END # Let's be explicit
    for ((i=1;i<=END;++i)); do echo $i; done
    

    seems to be the most memory-efficient way (it won't be necessary to allocate memory to consume seq's output, which could be a problem if END is very large), although probably not the “fastest”.

    the initial question

    eschercycle noted that the {a..b} Bash notation works only with literals; true, accordingly to the Bash manual. One can overcome this obstacle with a single (internal) fork() without an exec() (as is the case with calling seq, which being another image requires a fork+exec):

    for i in $(eval echo "{1..$END}"); do
    

    Both eval and echo are Bash builtins, but a fork() is required for the command substitution (the $(…) construct).

提交回复
热议问题