1

I want to programmatically create this output:

s1a
s2a
s3a
s4a
s5a

where I may go to any number of rows, not just 5. My approach is to use a for loop, referencing an environment variable iterator:

$ for i in $(seq 1 5); do echo s$ia ; done
s
s
s
s
s

How can I differentiate between the environment variable $i and the character a? I want to avoided referencing some $ia variable.

kilojoules
  • 9,768
  • 18
  • 77
  • 149

3 Answers3

4

Variable names are greedy, meaning they'll use as much of the text as possible to form a variable name. Hence s$ia is the literal s followed by the variable $ia.

You need to use braces to make it non-greedy:

echo s${i}a

This means the literal s the variable $i and the literal a:

pax> for i in $(seq 1 5) ; do echo s${i}a ; done
s1a
s2a
s3a
s4a
s5a

And keep in mind, modern bash versions can generate those sequences without resorting to the external seq:

for i in {1..5} ; do ...
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Is it worth pointing out that `i` is probably not an environment variable; it is just a shell variable. – Jonathan Leffler Mar 14 '17 at 03:04
  • @Jonathan, good point. I tend to often (erroneously) conflate them because even shell variables exist in the "environment" (common-English rather than `bash`-literal definition) of the shell. Since the behaviour here is independent of whether it's a shell or environment variable, I've removed the distinction. In future, I'll be more careful. – paxdiablo Mar 14 '17 at 03:17
3
  • There are no environment variables in your code, only shell variables.

    • Shell variables may also be environment variables (exported variables such as $PATH that are visible to all child processes, whether they're shells or not), but that's not the case here.
  • Shell variable names must be disambiguated from adjacent characters that could be part of a syntactically legal variable name by enclosing them in {...} - ${i}, in your case.

  • Unless you specifically want shell-variable references (possibly embedded in unquoted tokens) subjected to shell expansions, notably word-splitting and globbing, double-quote them - "s${i}a" in your case.

  • Use an arithmetic, C-style loop to create a memory-efficient loop with a variable number of iterations.

To put it all together:

$ n=5; for (( i = 1; i <= n; ++i )); do echo "s${i}a"; done
s1a
s2a
s3a
s4a
s5a
mklement0
  • 382,024
  • 64
  • 607
  • 775
1

bash brace expansion can handle that without loops or variables

$ echo s{1..5}a | tr ' ' '\n'
karakfa
  • 66,216
  • 7
  • 41
  • 56