Shell Parameter Expansion

Shell Parameter Expansion

官方文档 https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

${var} $”var” $var 辨析

在大多情况下, $var${var} 相同,大括号往往用于解决歧义,比如 $varboo --> ${var}boo

在上方添加双引号是为了防止变量中携带的多个空格被视作多个参数,加上双引号则变成单个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var="foo bar"
for i in "$var";
do
echo $i
done
>>>
foo bar
# 此时只循环一次,i 直接得到 "foo bar",如果使用
for i in $var;
do
echo $i
done
>>>
foo
bar
# 此时将会循环两次,按照空格分别取值,等价于 for i in "foo bar" ...

$var $var[@] ${var[@]} 辨析

参考文档 https://stackoverflow.com/questions/18135451/what-is-the-difference-between-var-var-and-var-in-the-bash-shell

根据 http://linux.die.net/man/1/bash手册

引用不带下标的数组等于引用下标为0的数组,那么

1
2
3
4
declare foo=(a b c)
$foo$foo[0]
# 这意味着
echo ${foo}$foo$foo[0] ⇔ ${foo[0]}

如果需要获取数组的所有元素,则需要使用 @

1
2
declare foo=(a b  c)
echo ${foo[@]}

需要注意的是,使用 @ 时必须携带括号,否则会先解析数组下标0,饭后拼接上 "[@]"

1
$foo[@] ⇔ "${foo}[@]""$foo[0][@]"

另外,如果你额外在花括号外围再套一层双引号,作为重新引用 Quotes Revisited

他会有一些区别,尤其在于你的参数内部有空格的时候

1
2
3
4
5
declare foo=("First Line" "Second Line")
for i in ${foo[@]}; # ⇔ for i in "First" "Line" "Second" "Line"
do
echo $i;
done

如上,此时 i 就会按照空格进行拆分,然后意料之外的读到别的东西,因此需要再套一个双引号进行转义

1
2
3
4
5
declare foo=("First Line" "Second Line")
for i in "${foo[@]}";
do
echo $i;
done

就能正确的按照原始的空格进行拆分、解析

Single Quotes & Double Quotes

单引号不能插入任何内容,但是双引号可以(变量、反引号、一些转义)

1
2
3
4
echo '$(echo "say something")'echo '$(echo "\"say somthing\" ")'
>>> "say something"
echo "$(echo "say something")"
>>> $(echo "say something")
  • 单引号会保留每个字符的字面值,单引号不能在单引号之间(即使使用转义)
  • 双引号除了保留字符的字面值,但是遇到 $ \ @ !` 时将执行特殊转换,必须使用转移符才能保留其字面值
  • 单双引号都不会转换 \n \b ,需要使用 ANSI-C 引用方法

举几个栗子

栗子的参考文档 https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash

1
2
3
apple="say so"
echo "$apple" >>> say so
echo '$apple' >>> $apple

注意,单引号并不识别、转换特殊字符,他们将保留字符的字面值

进一步的

1
2
echo " '$apple' " >>> 'say so'
echo ' "$apple" ' >>> "$apple"

单引号内的东西保留了字面值,尽管是双引号也一样,而双引号内的单引号不是特殊字符,保留字面值

另外,在单引号内尝试使用转移符来引入单引号是不可能的

1
2
echo '\'' >>> None
echo "\'" >>> \'

需要注意,因为 ' 在双引号内不是特殊符号,不会被转义

另一个栗子

1
2
3
a="A"
echo "$apple" >>> None
echo "${a}pple" >>> Apple

这里, apple 没有被定义,因此输出为空,为了让他转换 $a ,需要使用花括号括起来,同时,如果 $ 后面没有任何字符,其字面值将被保留

在双引号中使用反引号 ``` 或 $( ... ) 进行计算、执行,但单引号会保留字面值

1
"`echo hi`" >>> hi

$”var” & $’var’

这两种使用方式也有一些区别

  • $"var" 是标准的扩展引用,会转义特定的字符如 $ @ 等,但不会转移打印字符

  • $'var' 是ANSI-C风格引用,允许在其中转义 \n \b 之类的字符

    • 因此你可以在其中使用转移符号 \ 进行转义,而仅使用单引号会完全保留字面值,不会转义
    1
    2
    echo $'say \'so\'' >>> say 'so'
    echo 'say \'so\'' >>> 不工作

但不可以重复嵌套,比如

1
echo " $'\n' " >>> 不工作

Shell Parameter Expansion
https://blog.sukiloli.com/2024/11/11/ShellParameterExpansion/
作者
QLozin
发布于
2024年11月11日
许可协议