8.2 脚本编写

11 分钟阅读

在上一节中,我们学习了命令组合的基础知识。在本节中,我们将学习如何将这些命令组合封装成可重用的脚本,以便更高效地自动化各种任务。

脚本编写概述#

脚本是将一系列命令和逻辑组合在一起的可执行文件。使用脚本可以:

  • 提高效率:自动化重复性任务
  • 减少错误:避免手动操作的错误
  • 便于维护:集中管理复杂的逻辑
  • 易于分享:方便与团队成员共享

Bash 脚本基础#

1. 脚本结构#

一个基本的 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:管道中任何命令失败都导致整个管道失败
  • #:注释符号

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 -etrap
  • 检查返回值:检查命令的退出码
  • 提供清晰的错误信息:为用户提供有用的错误信息

示例:完善的错误处理

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
#!/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 脚本的基础知识(变量、函数、条件判断、循环、错误处理)和实用脚本示例,您可以创建强大、可重用的自动化工具。

记住以下要点:

  1. 从简单开始:先编写简单的脚本,逐步增加复杂性
  2. 注重实践:通过实际项目练习脚本编写
  3. 遵循最佳实践:使用错误处理、日志记录和性能优化
  4. 持续改进:不断优化和改进您的脚本

在接下来的章节中,我们将学习如何将这些脚本集成到 CI/CD 流程中,以及如何进行批处理操作和实际工作流应用。

标记本节教程为已读

记录您的学习进度,方便后续查看。