8.2 指令碼編寫
在上一節中,我們學習了命令組合的基礎知識。在本節中,我們將學習如何將這些命令組合封裝成可重用的指令碼,以便更高效地自動化各種任務。
指令碼編寫概述
指令碼是將一系列命令和邏輯組合在一起的可執行檔案。使用指令碼可以:
- 提高效率 :自動化重複性任務
- 減少錯誤 :避免手動操作的錯誤
- 便於維護 :集中管理複雜的邏輯
- 易於分享 :方便與團隊成員共享
Bash 脚本基础
1. 脚本结构
一個基本的 Bash 指令碼包含以下元素:
bash
#### 示例:基本脚本结构
bash
#!/bin/bash
# 脚本描述
# 作者:Your Name
# 日期:2026-01-01
# 设置脚本选项
set -e # 遇到错误立即退出
set -u # 使用未定义变量时报错
set -o pipefail # 管道中任何命令失败都导致整个管道失败
# 定义变量
PROJECT_DIR="./myproject"
MODEL="sonnet"
# 定义函数
main() {
echo "开始执行脚本"
setup_environment
generate_code
run_tests
echo "脚本执行完成"
}
# 执行主函数
main
#### 脚本元素说明#!/bin/bash:Shebang 行,指定指令碼直譯器set -e:遇到錯誤立即退出set -u:使用未定義變數時報錯set -o pipefail:管道中任何命令失敗都導致整個管道失敗#:註釋符號
bash
### 2\. 变量和参数
#### 示例:定义和使用变量
bash
#!/bin/bash
# 定义变量
PROJECT_DIR="./myproject"
MODEL="sonnet"
OUTPUT_FORMAT="json"
VERBOSE=true
# 使用变量
echo "项目目录: $PROJECT_DIR"
echo "模型: $MODEL"
# 条件使用变量
if [ "$VERBOSE" = true ]; then
claude --model "$MODEL" -p "分析项目" --verbose
else
claude --model "$MODEL" -p "分析项目"
fi
#### 示例:使用位置参数
bash
#!/bin/bash
# 使用位置参数
PROJECT_DIR=$1
MODEL=${2:-sonnet} # 默认值为 sonnet
OUTPUT_FORMAT=${3:-json}
# 检查参数
if [ -z "$PROJECT_DIR" ]; then
echo "错误:必须指定项目目录"
echo "用法: $0 <项目目录> [模型] [输出格式]"
exit 1
fi
# 使用参数
claude --model "$MODEL" \
--add-dir "$PROJECT_DIR" \
-p "分析项目" \
--output-format "$OUTPUT_FORMAT"
#### 示例:使用命名参数
bash
#!/bin/bash
# 定义命名参数
while getopts "d:m:f:v" opt; do
case $opt in
d) PROJECT_DIR="$OPTARG" ;;
m) MODEL="$OPTARG" ;;
f) OUTPUT_FORMAT="$OPTARG" ;;
v) VERBOSE=true ;;
\?) echo "无效选项: -$OPTARG" >&2; exit 1 ;;
esac
done
# 设置默认值
PROJECT_DIR=${PROJECT_DIR:-./myproject}
MODEL=${MODEL:-sonnet}
OUTPUT_FORMAT=${OUTPUT_FORMAT:-json}
VERBOSE=${VERBOSE:-false}
# 使用参数
if [ "$VERBOSE" = true ]; then
echo "项目目录: $PROJECT_DIR"
echo "模型: $MODEL"
echo "输出格式: $OUTPUT_FORMAT"
fi
claude --model "$MODEL" \
--add-dir "$PROJECT_DIR" \
-p "分析项目" \
--output-format "$OUTPUT_FORMAT"
### 3\. 函数定义
#### 示例:定义和使用函数
bash
#!/bin/bash
# 定义函数
setup_environment() {
echo "设置环境..."
claude --add-dir ./src --add-dir ./tests --add-dir ./config
}
generate_code() {
echo "生成代码..."
claude -p "生成代码"
}
run_tests() {
echo "运行测试..."
claude -p "运行测试"
}
# 定义主函数
main() {
setup_environment
generate_code
run_tests
}
# 执行主函数
main
#### 示例:带参数的函数
bash
#!/bin/bash
# 定义带参数的函数
analyze_file() {
local file=$1
local model=${2:-sonnet}
echo "分析文件: $file"
claude --model "$model" -p "分析 $file 的代码质量"
}
# 使用函数
analyze_file main.py
analyze_file utils.js opus
#### 示例:带返回值的函数
bash
#!/bin/bash
# 定义带返回值的函数
get_model() {
local task_type=$1
case $task_type in
"code_review")
echo "sonnet"
;;
"generation")
echo "opus"
;;
*)
echo "sonnet"
;;
esac
}
# 使用函数
MODEL=$(get_model "code_review")
echo "使用的模型: $MODEL"
### 4\. 条件判断
#### 示例:if 语句
bash
#!/bin/bash
# 检查文件是否存在
if [ -f "config.json" ]; then
echo "配置文件存在"
claude -p "使用配置文件"
else
echo "配置文件不存在"
claude -p "使用默认配置"
fi
# 检查命令执行结果
if claude -p "检查代码质量"; then
echo "代码质量检查通过"
else
echo "代码质量检查失败"
exit 1
fi
# 多条件判断
if [ -f "config.json" ] && [ -f "settings.json" ]; then
echo "所有配置文件都存在"
elif [ -f "config.json" ]; then
echo "只有 config.json 存在"
else
echo "配置文件不存在"
fi
#### 示例:case 语句
bash
#!/bin/bash
# 使用 case 语句
TASK_TYPE=$1
case $TASK_TYPE in
"review")
echo "执行代码审查"
claude -p "审查代码"
;;
"test")
echo "执行测试"
claude -p "运行测试"
;;
"deploy")
echo "执行部署"
claude -p "部署应用"
;;
*)
echo "未知任务类型: $TASK_TYPE"
echo "支持的任务类型: review, test, deploy"
exit 1
;;
esac
### 5\. 循环结构
#### 示例:for 循环
bash
#!/bin/bash
# 遍历文件
for file in *.py; do
echo "处理文件: $file"
claude -p "优化 $file 的性能"
done
# 遍历数组
projects=("frontend" "backend" "api")
for project in "${projects[@]}"; do
echo "处理项目: $project"
claude --add-dir "./$project" -p "分析项目"
done
# 数字循环
for i in {1..5}; do
echo "执行第 $i 次迭代"
claude -p "执行任务 $i"
done
#### 示例:while 循环
bash
#!/bin/bash
# 持续监控文件变化
while inotifywait -e modify *.py; do
echo "检测到文件变化"
claude -p "重新分析代码"
done
# 读取文件内容
while IFS= read -r line; do
echo "处理行: $line"
claude -p "处理: $line"
done < input.txt
# 条件循环
count=0
while [ $count -lt 5 ]; do
echo "计数: $count"
claude -p "执行任务 $count"
((count++))
done
### 6\. 错误处理
#### 示例:基本错误处理
bash
#!/bin/bash
# 设置错误处理
set -e
# 检查命令是否成功
if ! claude -p "生成代码"; then
echo "错误:代码生成失败"
exit 1
fi
# 使用 trap 捕获错误
trap 'echo "发生错误,退出码: $?"' ERR
claude -p "执行任务1"
claude -p "执行任务2"
claude -p "执行任务3"
#### 示例:高级错误处理
bash
#!/bin/bash
# 定义错误处理函数
handle_error() {
local exit_code=$1
local line_number=$2
echo "错误发生在第 $line_number 行,退出码: $exit_code"
# 清理操作
cleanup
exit $exit_code
}
# 设置错误处理
trap 'handle_error $? $LINENO' ERR
# 定义清理函数
cleanup() {
echo "执行清理操作..."
rm -f temp_files/*
}
# 执行任务
claude -p "执行任务1"
claude -p "执行任务2"
claude -p "执行任务3"
# 清理
cleanup
## 实用脚本示例
### 1\. 代码审查脚本
bash
#!/bin/bash
# 代码审查脚本
# 用法: ./code_review.sh [文件或目录] [模型]
set -e
# 参数处理
TARGET=${1:-.}
MODEL=${2:-sonnet}
# 检查目标是否存在
if [ ! -e "$TARGET" ]; then
echo "错误:目标不存在: $TARGET"
exit 1
fi
# 检查是文件还是目录
if [ -f "$TARGET" ]; then
echo "审查文件: $TARGET"
claude --model "$MODEL" -p "审查 $TARGET 的代码质量、安全性和性能"
elif [ -d "$TARGET" ]; then
echo "审查目录: $TARGET"
claude --model "$MODEL" --add-dir "$TARGET" -p "审查目录中的所有文件"
else
echo "错误:不支持的目标类型"
exit 1
fi
### 2\. 自动化测试脚本
bash
#!/bin/bash
# 自动化测试脚本
# 用法: ./auto_test.sh [测试类型]
set -e
# 参数处理
TEST_TYPE=${1:-all}
# 定义测试函数
run_unit_tests() {
echo "运行单元测试..."
claude -p "生成单元测试用例"
claude -p "运行单元测试"
}
run_integration_tests() {
echo "运行集成测试..."
claude -p "生成集成测试用例"
claude -p "运行集成测试"
}
run_e2e_tests() {
echo "运行端到端测试..."
claude -p "生成端到端测试用例"
claude -p "运行端到端测试"
}
# 根据测试类型执行测试
case $TEST_TYPE in
"unit")
run_unit_tests
;;
"integration")
run_integration_tests
;;
"e2e")
run_e2e_tests
;;
"all")
run_unit_tests
run_integration_tests
run_e2e_tests
;;
*)
echo "错误:未知测试类型: $TEST_TYPE"
echo "支持的测试类型: unit, integration, e2e, all"
exit 1
;;
esac
echo "所有测试完成"
### 3\. 文档生成脚本
bash
#!/bin/bash
# 文档生成脚本
# 用法: ./generate_docs.sh [输出目录]
set -e
# 参数处理
OUTPUT_DIR=${1:-./docs}
# 创建输出目录
mkdir -p "$OUTPUT_DIR"
# 提取函数文档
echo "提取函数文档..."
claude -p "提取所有函数的文档注释" --output-format json > functions.json
# 提取类文档
echo "提取类文档..."
claude -p "提取所有类的文档注释" --output-format json > classes.json
# 生成 Markdown 文档
echo "生成 Markdown 文档..."
claude -p "根据提取的信息生成 Markdown 文档" \
--input-format json \
--output-format markdown \
> "$OUTPUT_DIR/API.md"
# 生成 HTML 文档
echo "生成 HTML 文档..."
claude -p "根据提取的信息生成 HTML 文档" \
--input-format json \
--output-format html \
> "$OUTPUT_DIR/API.html"
echo "文档生成完成: $OUTPUT_DIR"
### 4\. 项目分析脚本
bash
#!/bin/bash
# 项目分析脚本
# 用法: ./analyze_project.sh [项目目录] [输出格式]
set -e
# 参数处理
PROJECT_DIR=${1:-.}
OUTPUT_FORMAT=${2:-json}
# 检查项目目录
if [ ! -d "$PROJECT_DIR" ]; then
echo "错误:项目目录不存在: $PROJECT_DIR"
exit 1
fi
# 分析项目结构
echo "分析项目结构..."
claude --add-dir "$PROJECT_DIR" \
-p "分析项目结构、代码质量和潜在问题" \
--output-format "$OUTPUT_FORMAT" \
> "project_analysis.$OUTPUT_FORMAT"
# 生成报告
echo "生成分析报告..."
claude -p "根据分析结果生成详细的报告" \
--input-format "$OUTPUT_FORMAT" \
--output-format markdown \
> "project_report.md"
echo "项目分析完成"
echo "分析结果: project_analysis.$OUTPUT_FORMAT"
echo "分析报告: project_report.md"
### 5\. 批量处理脚本
bash
#!/bin/bash
# 批量处理脚本
# 用法: ./batch_process.sh [文件模式] [处理类型]
set -e
# 参数处理
FILE_PATTERN=${1:-*.py}
PROCESS_TYPE=${2:-optimize}
# 定义处理函数
optimize_files() {
for file in $FILE_PATTERN; do
echo "优化文件: $file"
claude -p "优化 $file 的性能" > "${file%.py}.optimized.py"
done
}
review_files() {
for file in $FILE_PATTERN; do
echo "审查文件: $file"
claude -p "审查 $file 的代码质量" > "${file%.py}.review.md"
done
}
refactor_files() {
for file in $FILE_PATTERN; do
echo "重构文件: $file"
claude -p "重构 $file 的代码结构" > "${file%.py}.refactored.py"
done
}
# 根据处理类型执行处理
case $PROCESS_TYPE in
"optimize")
optimize_files
;;
"review")
review_files
;;
"refactor")
refactor_files
;;
*)
echo "错误:未知处理类型: $PROCESS_TYPE"
echo "支持的处理类型: optimize, review, refactor"
exit 1
;;
esac
echo "批量处理完成"
## 脚本最佳实践
### 1\. 脚本组织
* **模組化** :將複雜指令碼拆分成多個函式
* **配置化** :使用配置檔案管理引數
* **文件化** :為指令碼新增詳細的註釋和文件
#### 示例:模块化脚本
bash
#!/bin/bash
# 导入配置文件
source config.sh
# 导入函数库
source lib/functions.sh
# 主函数
main() {
initialize
execute_tasks
cleanup
}
# 执行主函数
main
### 2\. 错误处理- 設定錯誤處理 :使用
set -e和trap - 檢查返回值 :檢查命令的退出碼
- 提供清晰的錯誤資訊 :為使用者提供有用的錯誤資訊
bash
#### 示例:完善的错误处理
bash
#!/bin/bash
# 设置错误处理
set -e
set -u
set -o pipefail
# 定义错误处理函数
error_handler() {
local exit_code=$1
local line_number=$2
echo "错误: 脚本在第 $line_number 行失败,退出码: $exit_code"
cleanup
exit $exit_code
}
# 设置错误处理
trap 'error_handler $? $LINENO' ERR
# 定义清理函数
cleanup() {
echo "执行清理操作..."
rm -f temp_files/*
}
# 执行任务
main
### 3\. 日志记录- 記錄執行過程 :記錄指令碼的執行過程
- 記錄錯誤資訊 :記錄錯誤和警告資訊
- 記錄效能指標 :記錄執行時間和資源使用情況
bash
#### 示例:日志记录
bash
#!/bin/bash
# 定义日志函数
log() {
local level=$1
shift
local message="$@"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" >> script.log
}
# 使用日志函数
log INFO "脚本开始执行"
log INFO "执行任务1"
claude -p "执行任务1"
log INFO "任务1完成"
log INFO "脚本执行完成"
### 4\. 性能优化
* **並行處理** :使用後臺執行和 wait 提高效率
* **快取結果** :避免重複執行相同的命令
* **增量處理** :只處理變化的部分
#### 示例:性能优化
bash
#!/bin/bash
# 并行处理多个文件
for file in *.py; do
claude -p "分析 $file" > "${file%.py}.analysis.json" &
done
wait
# 使用缓存
CACHE_FILE="analysis.cache"
if [ -f "$CACHE_FILE" ]; then
log INFO "使用缓存结果"
cat "$CACHE_FILE"
else
claude -p "分析项目" > "$CACHE_FILE"
fi
## 总结指令碼編寫是自動化 Claude Code 任務的關鍵技能。透過掌握 Bash 指令碼的基礎知識(變數、函式、條件判斷、迴圈、錯誤處理)和實用指令碼示例,您可以建立強大、可重用的自動化工具。
記住以下要點:
- 從簡單開始 :先編寫簡單的指令碼,逐步增加複雜性
- 注重實踐 :透過實際專案練習指令碼編寫
- 遵循最佳實踐 :使用錯誤處理、日誌記錄和效能最佳化
- 持續改進 :不斷最佳化和改進您的指令碼
在接下來的章節中,我們將學習如何將這些指令碼整合到 CI/CD 流程中,以及如何進行批處理操作和實際工作流應用。