How can I write nested command substitutions?

Hello

How can write the nested command substitutions?

echo `expr substr $x 1 expr ${#x} - 1`

the above code is not working!

Thanks in advance

Regards
Chetanz

It should not be necessary to use "expr", ever.

$ echo ${x:1:${#x}-1}

(assuming your intention of extracting a substring of x; and those indexes are zero-based)

Should you actually ever need nested command substitutions, they're trivial if you use the modern syntax. Unless you are forced to use an ancient shell which does not support $(cmd), never use `cmd`.

One level of nesting using the deprecated, paleo-backtick command substitution syntax:

$ echo top `echo 0 \`echo 1\``
top 0 1

The simpler, modern syntax:

$ echo top $(echo 0 $(echo 1))
top 0 1

It may not seem like a big difference, but there are other subtleties involved. The backtick syntax has a more complicated and intrusive quoting mechanism whereby the top-level interferes with the code of nested subshells. If you don't know how it works, it will cause you pain. If, however, you do know how it works, it will also cause you pain.

With the modern syntax, anything in a substitution is written just as it is outside of a substitution, regardless of how deeply it's nested.

A contrived, comparitive demonstration of three levels of nesting. First, the modern syntax:

$ echo top $(echo 0 $(echo 1 $(echo 2 $(echo 3))))
top 0 1 2 3

Now the syntax of yore:

$ echo top `echo 0 \`echo 1 \\\`echo 2 \\\\\\\`echo 3\\\\\\\`\\\`\``
top 0 1 2 3

Regards,
Alister

3 Likes

Good post. I missed the subject title completely!

echo `expr substr $x 1 expr ${#x} - 1`

At least one reason your nested substitution does not work is because you only have one set of `` backticks. Regardless of whether you use the older backtick or newer $() syntax, nested substitution won't work if only one substitution. You would need another set of backticks around the internal expr command.

An easy, I would suggest better, alternative is "don't nest". Do one substitution, store the results in an intermediate variable. Use the intermediate variable in the next substitution.

It's simpler to understand, self-documenting, and easier to troubleshoot. The negative is it takes an extra line. A very small price to pay.

1 Like

Excellent advice.

Regards,
Alister