多步流水线 + HereDoc:一条脚本完成全自动内容生产
前两篇解决了"单次调用"和"输出可解析"。这一篇把多个调用串起来,做成流水线。
HereDoc:先解决长 prompt 的引号灾难
当任务描述超过一行、含引号嵌套时,-p "..." 会让你崩溃:
bash
# 引号打架,你也读不懂
claude -p "审查代码。规则1:检查类型。规则2:不能有"TODO"。规则3:检查"密钥"。" --allowed-tools "Read"
HereDoc 解法:
bash
claude -p "$(cat <<'PROMPT'
审查当前项目的代码变更。
检查规则(按优先级):
1. TypeScript 类型错误 ------ 必须修复
2. console.log 残留 ------ 提交前全部删掉
3. 硬编码密钥/token ------ 绝对禁止
输出 JSON 数组:[{file, line, rule, issue, severity}]
如果没有问题,输出空数组 []。
只输出 JSON。
PROMPT
)" --allowed-tools "Bash,Read" --model haiku
HereDoc 语法:<<'标记' 到单独一行 标记 之间的内容,原样传给命令。外层 $() 执行 cat,结果成为 -p 的参数。'PROMPT' 的单引号阻止 shell 二次解析里面的内容。
管道输入模式:任务本身也可以从管道来
前面是"数据走管道,指令写 -p"。也可以反过来------任务本身走管道:
bash
# 这三种写法效果一样:
# 1. -p 写指令
claude -p "把 Hello World 翻译成中文"
# 2. echo 管道
echo "把 Hello World 翻译成中文" | claude
# 3. HereDoc 管道
claude <<'EOF'
读取 CLAUDE.md,列出所有关于代码质量的规则,按优先级排序。
EOF
实际意义:任务内容可以来自另一个命令的输出。但需要注意:管道内容和 -p 不能同时用 ------管道进来的数据会成为 prompt,-p 会被忽略。正确做法是把动态内容拼进 -p 字符串:
bash
# ❌ 错误:管道 + -p 混用,-p 被忽略
cat ~/project/CLAUDE.md | claude -p "根据上面的规则审查代码"
# ✅ 正确:把动态内容拼进 -p
RULES=$(cat ~/project/CLAUDE.md)
claude -p "根据以下规则审查代码。规则:$RULES" --allowed-tools "Read,Bash" --model haiku
多步流水线:拆分大任务
一个任务走一步不靠谱(token 限制、中间结果无法审计),拆成多步,每步产出落盘。
css
搜索资料 列大纲 写初稿 去 AI 味
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ claude -p│ │ claude -p│ │ claude -p│ │ claude -p│
│ WebSearch│───→│ --continue│───→│ --continue│───→│ --continue│
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
▼ ▼ ▼ ▼
research.json outline.md draft.md final.md
四种数据传递方式:
| 方式 | 写法 | 场景 | 注意 |
|---|---|---|---|
| 文件落盘 | > /tmp/result.md,下一步 $(cat ...) 读 |
数据量大、需要审计 | 安全,推荐 |
$() 嵌入 |
RESULT=$(cat file); claude -p "...$RESULT" |
少量数据 | 和 -p 配合使用 |
--continue |
下一步加 --continue "$SID" |
保持会话上下文 | 必须第一步先 --session-id |
| 管道 | `echo "任务" | claude` | 单步任务 |
完整示例:文章自动生产线
bash
#!/bin/bash
# 全自动内容生产:搜资料 → 列大纲 → 写初稿 → 去 AI 味
TOPIC="Claude Code Hooks 入门"
SID="article-$(date +%s)" # 唯一会话 ID,所有步骤共用以保持上下文
# 第一步:搜索(--session-id 命名会话)
echo "=== 搜资料 ==="
claude -p "搜索「$TOPIC」的 3 篇高质量文章。输出标题、URL、核心观点。JSON 格式。" \
--session-id "$SID" --allowed-tools "WebSearch" --model haiku > /tmp/step1-research.json
# 第二步:列大纲(--continue 续上一步上下文)
echo "=== 列大纲 ==="
RESEARCH=$(cat /tmp/step1-research.json)
claude -p "根据以下资料,为「$TOPIC」生成文章大纲。引言 + 3 个要点 + 总结。\n资料:$RESEARCH" \
--continue "$SID" --allowed-tools "Read" --model haiku > /tmp/step2-outline.md
# 第三步:写初稿
echo "=== 写初稿 ==="
OUTLINE=$(cat /tmp/step2-outline.md)
claude -p "按以下提纲写一篇 1500 字技术文章。短句为主,人话解释技术概念。\n提纲:$OUTLINE" \
--continue "$SID" --allowed-tools "Read" > /tmp/step3-draft.md
# 第四步:去 AI 味
echo "=== 去 AI 味 ==="
DRAFT=$(cat /tmp/step3-draft.md)
claude -p "去掉以下文章中的「值得注意的是」「综上所述」等 AI 套话,长句拆短,被动改主动。\n文章:$DRAFT" \
--continue "$SID" --allowed-tools "Read" > /tmp/step4-final.md
echo "✅ 完成:/tmp/step4-final.md"
每步分析:
| 步骤 | Claude 看到什么 | 数据怎么传的 |
|---|---|---|
| 搜索 | 搜索指令,主题 | --- |
| 大纲 | 大纲指令 + 上一步的搜索结果 | $() 拼进 -p 字符串 |
| 初稿 | 写作指令 + 上一步的大纲 | $() 拼进 -p 字符串 |
| 去 AI 味 | 润色指令 + 上一步的初稿 | $() 拼进 -p 字符串 |
| 所有步骤 | 前面对话的完整记忆 | --continue "$SID" |
关键 :管道和
-p不能同时用------管道进来的数据会成为 prompt,-p会被忽略。正确做法是用$()把上一步结果拼进-p字符串。
运行方式:
bash
chmod +x ~/scripts/auto-article.sh
~/scripts/auto-article.sh
Shell 函数封装:把长命令缩短成单词
脚本写好之后还有一步:把常用命令缩短成一个词。
bash
# 加进 ~/.zshrc
ask() { claude -p "$*" --allowed-tools "Read,WebSearch,WebFetch" --model haiku; }
review() {
local files=$(git diff HEAD --name-only 2>/dev/null | tr '\n' ' ')
[ -z "$files" ] && { echo "无变更"; return; }
claude -p "审查以下文件的变更,列出最严重的 3 个问题:$files" \
--allowed-tools "Bash,Read" --model haiku
}
之后:
bash
ask React Concurrent Mode 是什么
review # 在当前仓库任意目录
注意 :必须用函数 () {},不能用 alias。因为 $(git diff ...) 需要在每次调用时重新执行,alias 在定义时就固定了。
系列目录:共 4 篇,从零到把 Claude Code 嵌入自动化脚本。