Pure Bash Bible 实用技巧:Bash 内置命令的高级用法
前言
在 Shell 脚本编程中,我们经常依赖各种外部命令来完成工作。然而,通过巧妙利用 Bash 内置功能,我们可以减少对外部命令的依赖,提高脚本性能和可移植性。本文将介绍一些基于 Bash 内置命令的高级技巧,这些技巧源自一个专注于纯 Bash 解决方案的技术项目。
使用 read 命令替代 sleep
技术背景: sleep
是一个常用的命令,但很多人不知道它实际上是外部命令而非 Bash 内置。在性能敏感的场景中,频繁调用外部命令会产生额外开销。
解决方案: Bash 4+ 提供了使用 read
命令实现类似 sleep
功能的方法:
read_sleep() {
# 用法: read_sleep 秒数
# 示例: read_sleep 0.5
read -rt "$1" <> <(:) || :
}
优化技巧: 对于需要频繁调用的场景,可以预先分配文件描述符:
exec {sleep_fd}<> <(:)
while 条件测试; do
read -t 0.001 -u $sleep_fd
done
注意事项:
- 这种方法比传统
sleep
命令更高效 - 仅适用于 Bash 4 及以上版本
检查程序是否在 PATH 中
三种等效方法:
type -p 程序名 &>/dev/null
hash 程序名 &>/dev/null
command -v 程序名 &>/dev/null
实用示例:
if ! type -p convert &>/dev/null; then
echo "错误: 未安装 convert,退出..."
exit 1
fi
技术比较:
type -p
直接返回可执行文件路径hash
会缓存查找结果command -v
是最符合 POSIX 标准的方法
使用 printf 获取格式化日期
技术背景: Bash 4+ 的 printf
内置了日期格式化功能,可以替代 date
命令。
实现方案:
date() {
# 用法: date "格式字符串"
# 参考: man strftime 查看格式说明
printf "%($1)T\\n" "-1"
}
使用示例:
printf '%(%Y-%m-%d %H:%M:%S)T\n' '-1'
# 输出: 2023-06-15 14:30:00
优势:
- 不依赖外部
date
命令 - 性能更高
- 支持完整的 strftime 格式
高级技巧集锦
1. 生成 UUID v4
uuid() {
C="89ab"
for ((N=0;N<16;++N)); do
B="$((RANDOM%256))"
case "$N" in
6) printf '4%x' "$((B%16))" ;;
8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;;
3|5|7|9) printf '%02x-' "$B" ;;
*) printf '%02x' "$B" ;;
esac
done
printf '\n'
}
注意:这不是加密安全的随机数。
2. 进度条实现
bar() {
((elapsed=$1*$2/100))
printf -v prog "%${elapsed}s"
printf -v total "%$(($2-elapsed))s"
printf '%s\r' "[${prog// /-}${total}]"
}
3. 获取脚本中所有函数
get_functions() {
IFS=$'\n' read -d "" -ra functions < <(declare -F)
printf '%s\n' "${functions[@]//declare -f }"
}
4. 绕过别名和函数
# 绕过别名
\ls
# 绕过函数
command ls
5. 后台运行命令
bkr() {
(nohup "$@" &>/dev/null &)
}
6. 不使用命令替换捕获函数返回值
to_upper() {
local -n ptr=${1}
ptr=${ptr^^}
}
foo="bar"
to_upper foo
echo "${foo}" # 输出: BAR
结语
通过本文介绍的技术,我们可以充分利用 Bash 内置功能,编写出更高效、更便携的脚本。这些技巧特别适用于以下场景:
- 需要减少外部依赖的环境
- 性能敏感的脚本
- 需要提高可移植性的场景
掌握这些纯 Bash 解决方案,将使你的脚本开发能力更上一层楼。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考