应避免循环中调用外部命令如date、hostname,改用变量缓存或$epochrealtime;优先用[[ ]]替代[ ]提升性能;文本处理禁用for line in $(cat file),改用while read流式读取。

避免在循环里反复调用 date、hostname 这类外部命令
每次执行 date 或 hostname 都要 fork 一个新进程,开销远高于变量赋值。脚本里如果在千次级循环中调用,可能拖慢几十倍。
- 把结果提前存进变量:
now=$(date +%s),后面直接用$now - 特别注意日志时间戳场景:别写成
echo "$(date): doing X"放在循环里 - 如果必须动态时间(比如每轮记录毫秒级时间),改用
$EPOCHREALTIME(bash 5.0+)或printf '%(%s.%N)T'(更轻量)
用 [[ ]] 替代 [ ] 做条件判断
[ ] 是 POSIX 兼容的外部命令(通常是 /usr/bin/[),而 [[ ]] 是 bash/zsh 内置关键字,无 fork 开销,且支持正则、模式匹配和更安全的字符串比较。
- 错误写法:
if [ "$var" = "abc" ]; then—— 引号漏掉或含空格时易出错,且启动子进程 - 正确写法:
if [[ $var == abc ]]; then—— 不强制引号(但建议仍加),不 fork,支持==和=~ - 注意兼容性:如果脚本需在 dash/sh 下运行,不能用
[[ ]];否则优先用它
批量处理文本别用 for line in $(cat file)
这种写法会先展开整个文件内容为单词列表,遇到空格、制表符、换行符都会被 word-splitting 破坏原始结构,还吃内存。实际性能差,语义也错。
- 正确方式是用
while read流式读取:while IFS= read -r line; do ...; done - 如果后续要用数组,先用
mapfile -t lines (bash),比 <code>arr=($(cat file))安全得多 - 涉及过滤/转换,优先交给
awk或sed—— 它们单次遍历、C 实现、不加载全文到 shell 变量中
函数内少用 export,全局变量慎用 declare -g
每次 export 都要更新环境块,频繁调用会触发系统调用;declare -g 在函数里修改全局变量看似方便,但会让变量生命周期和依赖关系变得隐晦,调试时难定位修改点。
- 只对真正需要传给子进程的变量
export(比如PATH、自定义回调钩子) - 函数尽量通过
echo返回值,或用local+ 参数传引用(如myfunc result_var,函数内用printf -v "$1" "%s" "$value") - 避免在循环中反复
export VAR=value—— 提前设好,或用子 shell 隔离:(export VAR=newval; cmd)
最常被忽略的是 I/O 和 fork 的叠加效应:一行看着简单的命令,背后可能是五次 exec、三次内存拷贝、两次缓冲区 flush。优化得从“这行会不会 spawn?”“这个变量是不是真要 global?”开始问。











