Bash 5.3 的命令替换 ${ command; }:省掉 fork,副作用留在当前 shell
Bash 5.3 于 2025 年夏发布,距 5.2 约三年。这一版的改动集中在脚本性能上。
参考:
命令替换的新形式
新增了一种在当前 shell 执行上下文中执行命令的命令替换,两种写法:
${ command; }捕获命令的标准输出,不 fork 子进程,也不经过管道。${| command; }在当前 shell 中执行,命令完成后把结果放进REPLY变量。
# 旧写法:fork 子进程 + 管道
out=$(printf '%s' "$x")
# 5.3:在当前 shell 执行,stdout 直接捕获进 out
out=${ printf '%s' "$x"; }
# 5.3:在当前 shell 执行,结果放进 REPLY
${| printf '%s' "$x"; }
out=$REPLY
和 $(command) 相比,省掉的是 fork 和管道开销。在循环里大量做字符串处理时,这部分省下来是可观的。
取舍也来自同一处:命令在当前 shell 上下文里执行,副作用会留下。变量赋值、cd、函数定义、set 之类状态的改动,都会作用到当前 shell,而不是随子进程退出一起消失。所以这类替换适合用在无副作用的纯计算/字符串处理上;有状态改动的命令还是用 $(...) 更稳。
其他新特性
GLOBSORT:新变量,决定路径名补全/展开结果的排序方式。关键字有name、size、blocks、mtime、atime、ctime、numeric、none,可升序或降序。GLOBSORT=sizecompgen新增-V varname:把生成的补全写入指定变量,而不是打印到标准输出。compgen -V candidates -W "start stop restart"read新增-E:使用 readline,并带上默认的 bash 补全(包括可编程补全)。也就是读输入时也能按 Tab 补全。read -E -p "file: " fsource新增-p PATH:用PATH参数替代$PATH来搜索文件。source -p /opt/app/lib utils.shBASH_MONOSECONDS:新的动态变量,若系统有单调时钟,返回其值。适合做不计入系统时间调整的耗时测量。$TIMEFORMAT允许最多 6 位精度(此前为 3 位)。bash_source_fullpathshopt 选项:让 bash 把完整路径写入BASH_SOURCE,并可在 configure 时设置默认值。fltexpr:新的可加载内建,像let那样做浮点算术。MULTIPLE_COPROCS现在默认启用。wait -n现在也能返回已通知过用户的终止进程替换与作业。若
[[中使用的正则编译失败,会打印错误信息;检查#!脚本前两行再判断是否为二进制。
源码层面
Bash 5.3 的源码更新以符合 C23,这意味着 Bash 不再能用 K&R 风格的 C 编译器编译。
Readline
Readline 是 Bash 用于命令行编辑、历史与补全的库。这一版的新特性:
search-ignore-case可绑变量:增量与非增量历史搜索忽略大小写。set search-ignore-case onexecute-named-command:从标准输入读取一个 readline 命令名并执行,emacs 模式默认绑到M-x。export-completions:把某个词的候选补全按既定格式写到标准输出,供其它进程消费。
构建
各发行版仓库会陆续收录 5.3;如果暂时找不到包,可以从源码构建。先装 build-essential,它依赖 libc6-dev、gcc、g++、make。