简体   繁体   中英

Modify loop variable bash

I want to be able to modify the value of the variable used in a for-in loop, from inside the loop.

Consider the following code:

#!/bin/bash
for i in {1..100} 
do 
    ((i--))
done;

Why is this loop not an infinite-loop? How can it be so?

Because it is not a C-style loop. The condition to exit the loop is not anyhow related to the value of i . It will just loop over the range from 1 to 100 and that's about it.

You can use C-style for-loop in bash if you have to:

for ((i=1; x<=100; i++)); do
    ((i--))
done

The for in loop in shell is not numeric, instead it works on a list of strings that is generated from the next token/construct after in and stored in memory. The indicated [control] variable takes the values from the list, one after another in each iteration; there is no way to manipulate that list. You can modify the variable inside the loop, ok, but at the next iteration it will get the next value of the list.

In other words, the control variable is not a control variable, it's only a placeholder to refer to the current items of the list (better: it does not "refer", it contains a copy of the referred item).

This means that the number of iterations is predetermined once, when the list of string is created. The number of iterations is equal to the number of strings in the list (of course you can break inside the loop).

Other languages have similar constructs, like for each ... , or using iterators and so on.

The real thing about for can be explained with the following example:

for a in *
do echo $a
done

is really interpreted as

for a in file1 file2 file3 file4 ie all the files in current directory
....

as is in fact perfectly legal to write

for a in 1 2 3 4 A B C D
...

Last note. I said the list of a for is kept in memory. I opened two terminals, launched a for in one, at checked the memory consumption in the other using free(1).

for a in 1 2 3; do sleep 50; done
...gives...
             total       used       free     shared    buffers     cached
Mem:        246596     224712      21884          0      33948      71584


for a in $(seq 1 1000000); do sleep 50; done
...gives...
             total       used       free     shared    buffers     cached
Mem:        246596     242864       3732          0       8400      24668

(notice the drop of buffers from 33948 to 8400, and the cached from 71584 to 24668). Finally ask for ten times more:

for a in $(seq 1 10000000); do sleep 50; done
...gives...
             total       used       free     shared    buffers     cached
Mem:        246596     243492       3104          0        688       8700

(more drop of buffers). The kernel is trying to find more memory and, doing that, slows down the poor little computer!

This shell for is very nice and powerful, but beware of the length of the list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM