我正在学习用 bash 编写 shell 脚本,我需要知道(...)和{...}. 编写脚本时如何在两者之间进行选择?
gle*_*man 101
如果您希望命令列表的副作用影响您当前的shell,请使用{...}
如果您想丢弃任何副作用,请使用(...)
例如,如果我:
$IFS一些命令,但我不想$IFS全局更改当前 shellcd某处,但我不想更改$PWD当前外壳值得注意的是,函数定义中可以使用括号:
正常用法:大括号:函数体在当前shell中执行;功能完成后副作用仍然存在
$ count_tmp() { cd /tmp; files=(*); echo "${#files[@]}"; }
$ pwd; count_tmp; pwd
/home/jackman
11
/tmp
$ echo "${#files[@]}"
11
Run Code Online (Sandbox Code Playgroud)异常用法:括号:函数体在子shell中执行;当子shell退出时副作用消失
$ cd ; unset files
$ count_tmp() (cd /tmp; files=(*); echo "${#files[@]}")
$ pwd; count_tmp; pwd
/home/jackman
11
/home/jackman
$ echo "${#files[@]}"
0
Run Code Online (Sandbox Code Playgroud)Dig*_*uma 29
来自官方bash 文档:
()
Run Code Online (Sandbox Code Playgroud)( list )将命令列表放在括号之间会导致创建一个子 shell 环境,并且 list 中的每个命令都将在该子 shell 中执行。由于列表是在子shell 中执行的,因此子shell 完成后变量赋值不再有效。
{}
Run Code Online (Sandbox Code Playgroud){ list; }将命令列表放在大括号之间会导致列表在当前 shell 上下文中执行。没有创建子shell。以下列表中的分号(或换行符)是必需的。
'{}' 中的代码在当前线程/进程/环境中执行并保留更改,更简洁地说,代码在当前范围内运行。
'()' 中的代码在 bash 的一个单独的子进程中运行,该子进程在执行后被丢弃。这个子进程通常被称为子 shell,可以被认为是一个新的、类似子进程的作用域。
例如,考虑以下...
~ # { test_var=test ; }
~ # echo $test_var
test
~ # ( test_var2=test2 )
~ # echo $test_var2
~ #
Run Code Online (Sandbox Code Playgroud)
请注意,在带有 '{}' 的第一个示例中,即使在关闭了 '}' 之后,变量仍然设置,而在带有 '()' 的示例中,变量未设置在 '()' 的范围之外。
还要注意 '{}' 和 '()' 语法差异。这 ”;” '{}' 中的代码总是需要分隔符,但 '()' 中的代码不需要。