Using a variable to control a BASH for loop
I know of 4 different ways to use a for loop:
1. for I in {1..10}; do echo $I; done| 2. for I in 1 2 3 4 5 6 7 8 9 10; do echo $I; done| 3. for I in $(seq 1 10); do echo $I; done| 4. for ((I=1; I <= 10 ; I++)); do echo $I; done I have a script which uses the 1st form of for loop. I'm trying to modify it to use a variable instead of a static hard-coded value in the section that controls the looping.of the for loop. I've tried all different ways of quoting and escaping the variable, and the problem is that the quoting chars and escape char are being translated and passed into the loop along with the value stored in the variable. For example, to change the start value of 1 to whatever value I want passed in through a variable: Change: for i in {1..100}; do <something>; done to: for i in {$a..10}; do <something>; done I have tried: {{$a}..10} and {`$a`..10}, to have the variable evaluated first. I have tried using the eval() function. I have tried single and double quotes and the backslash escape character. Nothing I've tried works. It's probably a syntax error, but as of now, I'm baffled. Can anyone shed some light on the problem and solution, please? Thanks! |
i don't really know what you mean but perhaps is it something like this?:
Code:
j=$(( RANDOM % 10 )) |
Interesting---it seems that the stuff in braces gets expanded before the variable is evaluated. I can't find a way around it.
Have you looked in ABS? (Advanced Bash Scripting Guide---on tldp.org) |
The problem is that the "brace expansion" is performed before the "variable expansion". See here for details about shell expansion, where they are listed in the order that they are expanded. Hence you have to use eval to let the bash do the variable substitution and then expand the resulting "extended brace" {1..10}. This should work
Code:
#!/bin/bash Code:
#!/bin/bash |
Yep!!
Here's the quote from ABS.. Quote:
|
following colucix's code, you can also save it in an array if you don't want to summon a subshell like:
Code:
eval "array=({${start}..10})" Code:
for a in "${array[@]}"; do ... |
Quote:
|
But option # 3 above works, why do you have to use the expansion method ? Just to make it harder ?
|
If I understand this correctly, the issue with the expansion is that the expansion happens before the parameter substitution. Thus
{$start...7} does not get expanded correctly. Why then does the array method work? |
Quote:
if this works: Code:
a=({1..10}) if a = 1: Code:
eval "array=({$a..10})" Code:
array=({1..10}) Quote:
|
Got it!!!---I had not appreciated exactly what "eval" does.
2 dots--of course. I was typing in a dark room. |
Quote:
I already have working scripts using form #1 'for' loops. That was the main reason to try and stick with it. Other related reasons are: 1. A minor edit would be simple to do globally using Vim, 2. I want to understand the inner workings of BASh; I've never been one to program 'by example' alone. Easy maintenance and gaining additional knowledge were good enough reasons for me, but NOT to make it harder. I never said I wasn't willing, or prepared, to switch to one of the other forms of the 'for' loop. Hope that clears it up. |
Quote:
That really helps alot. |
Quote:
|
Well, technically I tend to use # 3 because it's more versatile, and you won't have problems like this one. If I were writing scripts that I would have to update later ... that would be the one I'd pick. And, of course, I don't disagree finding out why # 1 causes problems, that helps to understand the inner workings, but in the end I wouldn't use that option.
|
All times are GMT -5. The time now is 04:19 PM. |