TransWikia.com

How to expand "word" in bash? Not talking about file wildcards

Unix & Linux Asked by Luis Santos on October 31, 2021

Sorry for so simple question, but I could not find a solution myself.

I run:

$ echo {1..4}
1 2 3 4

And that’s OK to me. But if I:

$ echo "{1..4}" > file

$ cat file
{1..4}

$ echo $(<file)
{1..4}

$ echo $(cat file)
{1..4}

I’m looking for a way to expand the string {1..4} that’s inside the file file using echo, without success.

2 Answers

You are just not using the right tool for the job:

[user@host dir]$ ksh
$ echo "{1..4}" > file
$ cat file
{1..4}
$ echo $(<file)
1 2 3 4
$ echo $(cat file)
1 2 3 4

Jokes aside, the order of expansions in Bash is:

  1. brace expansion;
  2. tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion);
  3. word splitting;
  4. and filename expansion.

Thus, in echo $(cat file), the output of the (unquoted) command substitution undergoes word splitting and filename expansion only—remaining unchanged because it doesn't include pattern matching characters (and assuming your IFS variable does not include {, 1, ., 4 or }).

While some expansions can be nested, the result of an expansion is generally not parsed again for characters that would trigger expansions from stages up to the current one. (For good reasons: think about foo=$foo; echo "$foo").

To have brace expansion applied to the content of file you need to build a new command line and let the shell parse and execute it. One way is eval, as shown in this other answer you have. Alternatively, you may use process substitution:

$ . <(printf '%s ' echo; cat file)
1 2 3 4

Note that, in both cases, the whole content of file will be parsed and executed in the current environment.

Similarly, but executing in the separate environment of a new bash process:

$ bash <<<$( printf "%s " echo; cat file; )
1 2 3 4

As an aside, ksh93 (the shell I used in my first code block) behaves in a peculiar way: brace expansion is performed at a later stage, as part of field splitting, and the result of previous expansions is parsed anew to detect brace expressions1:

$ bash -c 'echo {1..$(printf %s 3)}' mybash
{1..3}
$ ksh -c 'echo {1..$(printf %s 3)}' myksh
1 2 3

1 As Stéphane Chazelas noted in comments, this behavior of ksh93 can be considered a bug and is not POSIX conformant, since it makes it possible for $var not to expand to the value of var.

Answered by fra-san on October 31, 2021

I think you are looking for this:

eval "echo $(cat file)"

eval constructs a command which is then executed by the shell.

Answered by laktak on October 31, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP