helpThe GNU Bourne-Again SHell - Support: sr #107974, sequence expression boundaries...

 
 

sr #107974: sequence expression boundaries should be variable

Submitted by:  Bep Rinto <beprinto>
Submitted on:  Wed 29 Feb 2012 04:58:21 PM UTC  
 
Category: NonePriority: 5 - Normal
Severity: 1 - WishStatus: None
Privacy: PublicAssigned to: None
Open/Closed: OpenOperating System: None

Add a New Comment (Rich MarkupRich Markup):
   

You are not logged in

Please log in, so followups can be emailed to you.

 

Thu 28 Nov 2013 10:07:06 AM UTC, comment #1:

n=1
m=10
printf "%s\n" foo{test,$n,$m}

already works, because brace expansion happens before everything, including parameter substition.

As for variables in range expressions, you can use eval, even if it's a bit clunky.

eval printf '%03d\\n' "{$n..$m}"

or more usefully
eval "for i in {$n..$m};do echo \$i;done"

Obviously, using eval makes properly quoting your variables a chore.

It's probably too late to re-design bash's brace expansion to happen after parameter expansion, for example. There are certainly scripts that would break because either they are using brace expansion to produce parameter names, or they have parameters containing braces, or otherwise do something that would be different with a different order.

The chances of anything breaking if sequence expansion was split off from the usual brace expansion and done later is lower. This might be doable. It would still break scripts that expand parameters containing anything that looks like a sequence, without quoting it.
e.g.
foo="{1..4}"
some_program -r $foo $bar "$@"

Having the sequence expansion part of brace expansion TRIGGER parameter expansion on its inputs could work, although there could still be wrapper scripts for programs that take arguments formatted like {1..4}, that would then break.
e.g.
some_program {$1..$2} "$3"

Would have been fine if "{$1..$2}" was quoted. I would have quoted it if I was writing it, and there are hopefully very few cases of scripts like that.

If it's not too much trouble, triggering parameter expansion for things in an otherwise well-formed brace sequence-expansion seems like a good idea to me. Expanding them twice if it turns out not to be a valid sequence expression, after expansion, seems like a small price to pay. This would ONLY affect scripts like
x=xxx y=yyy
foo='$x' bar='$y'
some_program {$foo..$bar}
which would then get {xxx..yyy} instead of {$x..$y} as input to their program. ({...} if there were no parameters called foo and bar, or a sequence if x and y were numeric or single characters.

And then only when the braces weren't even double-quoted, so unlikely to affect e.g. perl oneliners in bash scripts.

People using eval as I suggested to get the desired behaviour with current bash could be affected if they were expecting word-splitting (on the eval command line) before sequence expansion (not done until eval gets its hands on it, in current bash). You can simulate the effect by using {1..5} instead of {$n..$m}, and quoting or unquoting the braces. set -x is helpful for seeing the canonically quoted input to eval and printf
tail="2 2"
eval printf '%s\\n' {$n..$m}"$tail"
# is affected by pre-eval sequence expansion:
# It becomes:
eval printf '%s\\n' {1..5}"$tail"
printf %s\\n 1$tail 2$tail ...
# with current bash, it becomes:
eval printf '%s\\n' \{1..5}"$tail"
printf %s\\n {1..5}2 2

As long as the sequence is quoted in the eval, the result won't change if bash ever decides to do extra parameter expansion for sequences. So this is a Good Idea

eval printf '%s\\n' "{1..5}\"\$tail\"" # full quoting. In this case, it doesn't matter if the sequence expansion happens before eval or not, as $tail isn't expanded into something that can be word-split until after eval.
printf %s\\n {1..5}"$tail"

So after typing all that, I just realized that your examples for sequences with variables can be handled by either using seq(1), or by using the arithmetic evaluation / C style of for loop. If you really want to tack things on to each item in the sequence, maybe eval is the way to go. If you have anything more complex than that to do, just do it inside a for loop.

n=1 m=10 k=2 tail="split me"
for (( i=n ; i <= m ; i += k )); do echo "$i$tail";done

So in summary, just doing brace expansion at a later time is probably not a good idea, but doing an extra round of parameter expansion on possible sequences would be minimally-incompatible and a useful shorthand in some cases. Given the availability of eval and arithmetic for loops, all you'd save is forcing people to remember that one or the other exists.

Some cases will be better served by eval (e.g. when you want to tack on extra text to each element and pass the whole sequence to something in one command). If you really just wanted to loop over a sequence, then clearly for (( )) instead of the for var in construct is perfect.

I'd suggest this bug should be closed as wontfix, as the feature doesn't add anything you can't easily do already (just have to remember that the other syntax options are there).

Peter Cordes <pcordes>
Wed 29 Feb 2012 04:58:21 PM UTC, original submission:

Currently a brace expansion sequence expression supports only fixed boundaries, but this is inflexible and limiting. It should be possible to specify sequence expressions using variable bounds. For example:

for i in {$n..$m}; do command $i; done

In this case the variables must expand to an integer value.
This idea applies to other brace expansions as well, such as:

for i in {$n..$m..$k}; do cmd $i; done

and:

mkdir /usr/local/src/bash/{old,new,$var1,$var2}

Bep Rinto <beprinto>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach File(s):
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -unavailable- added by pcordes (Posted a comment)
  • -unavailable- added by beprinto (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

    Please enter the title of George Orwell's famous dystopian book (it's a date):

     

     

    No Changes Have Been Made to This Item

    Back to the top


    Powered by Savane 3.1-cleanup