欢迎大家来到IT世界,在知识的湖畔探索吧!
Bash 脚本编程是一门艺术,掌握一些核心技巧能让你的脚本更健壮、高效且易于维护。以下是一份精华总结:
Bash 编程技巧精华总结
1. 脚本头部与健壮性设置
这是每个生产级 Bash 脚本的基石。
Shebang (Hashbang): 指定解释器。
#!/bin/bash
content_copy
download
Use code with caution.
Bash
推荐使用 /usr/bin/env bash 来确保在不同系统上的兼容性:
#!/usr/bin/env bash
content_copy
download
Use code with caution.
Bash
set -euo pipefail (黄金法则):
set -e: 遇到未捕获的错误时立即退出脚本。
set -u: 尝试使用未定义的变量时立即退出脚本。
set -o pipefail: 管道中任一命令失败时,整条管道返回失败状态。
#!/usr/bin/env bash
set -euo pipefail
IFS=#39;\n\t’ # 推荐设置,防止单词分割和文件名中的空格问题
content_copy
download
Use code with caution.
Bash
IFS=#39;\n\t’: 改变内部字段分隔符,让 for 循环和 read 等命令默认按行(而不是空格)处理,避免文件名或变量中包含空格导致的问题。
2. 变量与参数
变量声明与使用:
my_var=”Hello World”
echo “$my_var” # 始终引用变量!
content_copy
download
Use code with caution.
Bash
${var} 语法: 当变量后面紧跟字母或数字时,使用花括号避免歧义。
file_prefix=”log”
# echo “$file_prefix_2023” # 错误,Bash会找file_prefix_2023这个变量
echo “${file_prefix}_2023.txt” # 正确
content_copy
download
Use code with caution.
Bash
特殊变量:
$0: 脚本文件名。
$1, $2, …: 传递给脚本的命令行参数。
$#: 传递给脚本的参数数量。
$@: 所有参数,保持参数的独立性(推荐用于循环)。
$*: 所有参数,作为单个字符串。
$?: 上一个命令的退出状态 (0 为成功,非0 为失败)。
$: 当前脚本的PID。
$BASHPID: 当前 Bash 进程的PID(在子shell中也可用)。
参数扩展 (Parameter Expansion):
${var:-default}: 如果 var 为空或未设置,则使用 default。
${var:=default}: 同上,但会设置 var 为 default。
${var:?error_msg}: 如果 var 为空或未设置,则输出 error_msg 并退出。
${var%suffix}: 从 var 尾部删除最短匹配的 suffix。
${varprefix}: 从 var 头部删除最长匹配的 prefix。
${var/search/replace}: 替换 var 中第一个 search 为 replace。
${var//search/replace}: 替换 var 中所有 search 为 replace。
${#var}: 获取 var 的长度。
${array[@]}: 遍历数组所有元素。
name=${1:-“Guest”} # 如果第一个参数未提供,则默认为 “Guest”
echo “Hello, ${name}”
path=”/usr/local/bin/myscript.sh”
echo “Filename: ${path*/}” # myscript.sh
echo “Directory: ${path%/*}” # /usr/local/bin
content_copy
download
Use code with caution.
Bash
3. 条件判断与循环
[[ … ]] vs [ … ]: 推荐使用 [[ … ]] (Bash 专用),因为它更强大、更安全、更易读。
支持正则表达式匹配 =~。
不需要对特殊字符进行引用。
避免单词分割。
# 字符串比较
if [[ “$name” == “Alice” ]]; then
echo “Found Alice”
fi
# 字符串是否为空
if [[ -z “$var” ]]; then # -z 字符串长度为0
echo “Var is empty”
fi
if [[ -n “$var” ]]; then # -n 字符串长度非0
echo “Var is not empty”
fi
# 数值比较 (使用 ((…)))
if (( num1 > num2 )); then
echo “num1 is greater”
fi
# 文件判断
if [[ -f “/path/to/file.txt” ]]; then # -f 是文件
echo “File exists”
fi
if [[ -d “/path/to/dir” ]]; then # -d 是目录
echo “Dir exists”
fi
content_copy
download
Use code with caution.
Bash
case 语句: 处理多分支条件判断。
case “$action” in
start|run)
echo “Starting…”
;;
stop)
echo “Stopping…”
;;
*) # 默认匹配
echo “Invalid action: $action” >&2
exit 1
;;
esac
content_copy
download
Use code with caution.
Bash
for 循环:
遍历列表:
for item in file1.txt file2.txt “file with spaces.txt”; do
echo “Processing: $item”
done
content_copy
download
Use code with caution.
Bash
遍历数组:
files=(“file1.txt” “file2.txt” “file with spaces.txt”)
for file in “${files[@]}”; do # 必须加双引号和@,否则有空格的文件名会被分割
echo “Processing: $file”
done
content_copy
download
Use code with caution.
Bash
C 风格循环:
for (( i=0; i<5; i++ )); do
echo “Count: $i”
done
content_copy
download
Use code with caution.
Bash
while 循环:
按行读取文件:
while IFS= read -r line; do # -r 避免反斜杠转义
echo “Line: $line”
done < “input.txt”
content_copy
download
Use code with caution.
Bash
无限循环:
while true; do
# …
sleep 1
done
content_copy
download
Use code with caution.
Bash
4. 函数
定义函数:
my_function() {
echo “Function name: ${FUNCNAME[0]}” # 获取当前函数名
echo “Arguments: $@”
echo “First arg: $1”
local var=”inside_func” # 局部变量,避免污染全局环境
echo “$var”
return 0 # 返回退出状态码
}
my_function “arg1” “arg2”
content_copy
download
Use code with caution.
Bash
返回值:
退出状态码: return 0 (成功) 或 return 非0 (失败)。用于判断函数是否执行成功。
实际数据: 通过 echo 或 printf 将数据输出到标准输出,然后通过命令替换 ($()) 捕获。
get_data() {
echo “Some useful data”
return 0
}
result=$(get_data)
if [[ $? -eq 0 ]]; then
echo “Function returned: $result”
fi
content_copy
download
Use code with caution.
Bash
5. 输入/输出与重定向
输出: echo (简单,常用) 和 printf (格式化输出,更强大)。
echo “Hello Bash”
printf “Name: %s, Age: %d\n” “Alice” 30
content_copy
download
Use code with caution.
Bash
输入: read。
read -p “Enter your name: ” name
echo “Hello, $name!”
content_copy
download
Use code with caution.
Bash
重定向:
>: 标准输出重定向到文件(覆盖)。
>>: 标准输出重定向到文件(追加)。
<: 从文件读取标准输入。
2>: 标准错误重定向到文件。
&>: 将标准输出和标准错误都重定向到文件。
/dev/null: 丢弃输出。
ls > file_list.txt 2> error.log # 将ls结果写入file_list.txt,错误写入error.log
command_that_might_fail &> /dev/null # 丢弃所有输出
content_copy
download
Use code with caution.
Bash
管道 |: 将一个命令的输出作为另一个命令的输入。
ls -l | grep “.sh” | sort -r
content_copy
download
Use code with caution.
Bash
6. 错误处理与调试
trap 命令: 捕获信号并执行命令。常用于清理临时文件。
cleanup() {
echo “Performing cleanup…”
rm -f “/tmp/my_temp_file_$”
}
trap cleanup EXIT # 在脚本退出时(无论成功失败)执行 cleanup 函数
trap ‘echo “An error occurred on line $LINENO.” >&2’ ERR # 捕获错误
content_copy
download
Use code with caution.
Bash
调试:
set -x: 打印执行的命令。
bash -x script.sh: 直接用 -x 启动脚本。
在特定位置添加 set -x 和 set +x 来只调试部分代码。
set -x # 开始调试
# … 你的代码 …
set +x # 停止调试
content_copy
download
Use code with caution.
Bash
7. 常见陷阱与最佳实践
始终引用变量: 这是最常见的错误来源。”$var” 而不是 $var。
# 错误示例:当 file_path 包含空格时会出错
# rm $file_path
# 正确示例
rm “$file_path”
content_copy
download
Use code with caution.
Bash
避免使用 ls | while read: 因为管道会创建子shell,在子shell中对变量的修改不会影响父shell。
推荐方案 1 (处理文件名):find -print0 | xargs -0
find . -maxdepth 1 -type f -print0 | while IFS= read -r -d #39;\0′ file; do
echo “Processing: $file”
done
content_copy
download
Use code with caution.
Bash
推荐方案 2 (读取普通行):
while IFS= read -r line; do
# …
done < <(ls -l) # 使用进程替换,避免子shell
content_copy
download
Use code with caution.
Bash
dirname 和 basename: 获取路径的目录部分和文件名部分。
script_dir=$(dirname “$0”)
script_name=$(basename “$0”)
echo “Script is $script_name in $script_dir”
content_copy
download
Use code with caution.
Bash
使用 getopts 处理命令行选项: 比手动解析 $1, $2 更健壮。
while getopts “a:b:c” opt; do
case “$opt” in
a) arg_a=”$OPTARG” ;;
b) arg_b=”$OPTARG” ;;
c) flag_c=true ;;
*) echo “Usage: $0 [-a value] [-b value] [-c]”; exit 1 ;;
esac
done
shift $((OPTIND-1)) # 移除已处理的选项
content_copy
download
Use code with caution.
Bash
临时文件: 使用 mktemp 安全地创建临时文件。
tmp_file=$(mktemp)
echo “This is temp data” > “$tmp_file”
# … 使用 tmp_file …
rm -f “$tmp_file” # 别忘了清理
content_copy
download
Use code with caution.
Bash
避免 eval: eval 可以执行任意字符串,非常危险。除非你完全理解其风险并能确保输入安全,否则应避免使用。
权限: 确保脚本有执行权限 (chmod +x script.sh)。
注释: 良好的注释能大大提高脚本的可读性和可维护性。
掌握这些技巧将使你能够编写出更专业、更可靠的 Bash 脚本。记住,实践是最好的学习方式!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/135301.html