[Linux] [bash] Command Substitution

本文深入探讨了Shell命令替换的使用方式、如何去除尾随换行符、参数展开后的特殊字符处理,以及如何在命令中正确应用这些技巧。通过具体实例展示了在不同场景下如何有效地利用Shell命令替换特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. If a command substitution occurs inside double-quotes, field splitting and pathname expansion shall not be performed on the results of the substitution.

######################### Example 1 #########################

`echo a b` = $(echo a b)     # 2 args: a and b
"`echo a b`" = "$(echo a b)"   # 1 arg: "a b"
`echo` = $(echo)        # no arg
"`echo`"       # one empty arg

######################### Example 2 #########################

if the output is ("na m\ne") as a whole using this style:
`echo -e "na m\ne"` = $(echo "\"na m\ne\"")
then, the <newline>, <space> and <tab> are treated as delimiter, delimit a field.
The double-quote in output is a just a charater and meaningless.
So the result are three parts: ("na), (m), (e").

if the output is ("na m\ne") as a whole using this style:
"`echo -e "na m\ne`" = "$(echo "\"na m\ne\"")"
then, the <newline>, <space> and <tab> are treated NOT as delimiter.
The double-quote in output is a just a charater and meaningless.
So the result is one parts: ("na m\ne").
Because the command substitution occurs inside double-quotes, so field splitting not be performed on the result.


2. Command substitution can remove trailing newlines

######################### Example 1 #########################

Command substitution can remove trailing newlines as below:
$ echo -e $(echo -e "a\nb\nc")
a b c

Command substitution will not remove trailing newlines in double-quotes as below:
$ echo -e "$(echo -e "a\nb\nc")"
a
b
c
In this case, "a\nb\nc" is a whole.


3. the backslash (\) and double-quotes (") are meaningless after substitution.
    the backslash (\) and double-quotes (") are still meaningful after redirection.

After parameter expansion ( ${...} ), command substitution ( $(...) ), and arithmetic expansion ( $((...)) ),
 the shell shall scan the results of expansions and substitutions that did not occur in double-quotes forfield splitting and multiple fields can result.
I.e. it does not perform a analyze on any backslash or double-quotes, just see them as normal characters; then just split field.
The field splitting result is split into white-space separated words.

######################### Example 1 #########################

i want to find file (a b) and file (c):
$ find a\ b c
find: `a b': No such file or directory
find: `c': No such file or directory

Then, i want to use command substitution as the parameters of "find".
the output of command substitution are as the parameters passed to "find" command.

$ find $(echo -e "a b\nc")
find: `a': No such file or directory
find: `b': No such file or directory
find: `c': No such file or directory
the parameters pass to "find" command is three parts: (a), (b), (c), the newline character is removed by $(...).
This is not what i want.

$ find $(echo -e "a\ b\nc")
find: `a\\': No such file or directory
find: `b': No such file or directory
find: `c': No such file or directory
the parameters pass to "find" command is three parts: (a\), (b), (c), the newline character is removed by $(...).
the backslach (\) characters are meaningless.

it still not ok even if i add double-quotes on (a b):
$ find $(echo -e "\"a b\"\nc")
find: `"a': No such file or directory
find: `b"': No such file or directory
find: `c': No such file or directory
the parameters pass to "find" command is three parts: ("a), (b"), (c), the newline character is removed by $(...).
the double-quotes (") characters are meaningless.
This is not what i want.

$  find "$(echo -e "a b\nc")"
find: `a b\nc': No such file or directory
the parameters pass to "find" command is a whole part: (a b\nc), the newline character is not removed. 
This is not what i want.

######################### Example 2 #########################

But if the output are serveral parts as "\"na me1\"\n\"Nam e2\"\n\"n AME3\"" originally represent three parts: ("na me1"), ("Nam e2") and ("n AME3").
When using $(echo "\"na me1\"\n\"Nam e2\"\n\"n AME3\"")
the result are several parts: ("na), (me1"), ("Nam), (e2"), ("n), (AME3")
When using "$(echo "\"na me1\"\n\"Nam e2\"\n\"n AME3\"")"
the result is one part: ("na me1"\n"Nam e2"\n"n AME3")
Neither way is OK using $(echo "na me1\nNam e2\nn AME3") or "$(echo "na me1\nNam e2\nn AME3")", 
 originally represent three parts: ("na me1"), ("Nam e2") and ("n AME3").

######################### Example 3 #########################

>> cleartool $(echo -e "\"a b\"\nc")
cleartool: Error: Unrecognized command: ""a"
# cleartool only get ("a), (b"), (c) as its input, the newline is removed by $(...).
# The double-quotes in the parameter after substitution are meaningless for "cleartool" command.

>> echo -e "\"a b\"\nc" | cleartool
cleartool: Error: Unrecognized command: "a b"
cleartool: Error: Unrecognized command: "c"
# cleartool only get ("a b"\nc) as its input, and when read  a newline charactor(\n),i guess it execute at once, then after execute, read the following input.
# The double-quotes in stdin (which is after redirection) are still meaningful for "cleartool" command.

4. Reference

Shell Command Language
Command Substitution




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值