问题描述
我正在用bash学习shell脚本,我需要知道(...)
和{...}
之间的区别。在编写脚本时如何在两者之间进行选择?
最佳解决思路
如果希望命令列表的side-effects影响当前shell,请使用{...}
如果要丢弃任何side-effects,请使用(...)
例如,如果我:我可能会使用子shell:
-
想要为一些命令改变
$IFS
,但我不想为当前shell全局改变$IFS
-
cd
在某处,但我不想为当前的shell更改$PWD
值得注意的是括号可以在函数定义中使用:
-
正常用法:大括号:函数体在当前shell中执行;功能完成后,side-effects保留
$ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; } $ pwd; count_tmp; pwd /home/jackman 11 /tmp $ echo "${#files[@]}" 11
-
不寻常的用法:括号:函数体在子shell中执行;子壳退出时,side-effects消失
$ cd ; unset files $ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}") $ pwd; count_tmp; pwd /home/jackman 11 /home/jackman $ echo "${#files[@]}" 0
次佳解决思路
来自官方bash documentation:
()
( list )
Placing a list of commands between parentheses causes a subshell environment to be created, and each of the commands in list to be executed in that subshell. Since the list is executed in a subshell, variable assignments do not remain in effect after the subshell completes.
{}
{ list; }
Placing a list of commands between curly braces causes the list to be executed in the current shell context. No subshell is created. The semicolon (or newline) following list is required.
第三种解决思路
‘{}’中的代码在当前线程/进程/环境中执行并保留更改,更简洁地说,代码在当前范围内运行。 ‘()’中的代码在bash的单独子进程内运行,该进程在执行后被丢弃。这个子进程通常被称为sub-shell,可以被认为是一个新的child-like范围。
作为一个例子考虑以下……
~ # { test_var=test }
~ # echo $test_var
test
~ # ( test_var2=test2 )
~ # echo $test_var2
~ #
请注意,在'{}’的第一个示例中,即使在关闭’}’之后,变量仍然设置,而在'()’的示例中,变量未设置在'()’的范围之外。
第四种思路
(...)
用于在sub-shell中运行代码。使用的代码{...}
将不会用于sub-shell。