跳到正文
docai.cc

DOCAI · 课程 · L3 · 24 分钟 · 命令参考

`cat file | claude -p` — 处理管道内容

把日志、diff、接口返回直接喂给 claude -p:标准输入与提示词如何拼接、JSON 结果怎么接、退出码和权限在脚本里怎么管。

Claude Code 程序员 · CLI 命令详解

你将学会

  • 能把日志、diff、接口返回通过管道交给 claude -p 处理
  • 能写清提示词与素材的边界,避免它抓错重点
  • 能在脚本里判断退出码、控制权限并记录花费

一条管道能省掉多少复制粘贴

线上日志几万行,你只想知道哪几类报错最该先修。改完代码,你想在提交前听一遍不同意见。接口返回一大段数据,你想要一句人话总结。这些素材本来就在文件或命令输出里,复制进对话框既慢,也容易漏掉关键行。

claude -p 是单次执行模式:给出任务,拿到结果,进程结束,不进入交互界面。它同时读取标准输入,所以 shell 的管道可以直接把内容送进来。

grep -i "error" logs/app.log | claude -p "按出现频率归类这些报错,指出最该先修的三类"

左边筛选,右边判断。整节课讲的就是这条分工线。

它收到的到底是什么

管道内容不是附件,而是和你写在命令里的那句话拼成同一段输入。两件事因此要交代清楚:

  • 指令要具体:看什么、按什么标准排、输出几句、用什么语言。
  • 素材要说明:这是哪个时间段的日志、哪些行可以忽略、字段含义是什么。

素材里夹着代码或表格时,加一行分隔,让它知道正文从哪开始。内容太长就先裁剪:只取相关时段、只留报错行、去掉重复堆栈。省下的 token 是实打实的成本,更能减少它被无关内容带偏的机会。上下文如何计量,见上下文窗口。

三个马上能用的组合

审查改动。 diff 直接进管道,提示词只写关注点:

git diff | claude -p "只报会改变运行结果的问题,按文件分组;格式和命名不要提"

整理提交记录。 让它输出纯文本,直接贴进发布说明:

git log --oneline v1.2..HEAD | claude -p "按新增、修复、其他分三段整理,不要补充记录里没有的内容"

读接口数据。 先取数,再让它挑异常:

curl -sS https://example.com/api/stats | claude -p "找出偏离日常范围的指标,各用一句话解释可能原因"

三个例子的结构一致:命令负责取数,提示词负责定性,输出约束成你要的形状。路径和地址都要换成你自己的;先拿一小段样本验证提示词,确认输出可用,再放到全量数据上跑。

让结果能被脚本接住

给人看的回答是段落,给程序用的回答要结构化。加 --output-format json,再从中取正文。返回体里除了 result,通常还有 is_error、total_cost_usd、duration_ms 这类字段;字段名随版本变化,写解析前先打印一份看结构。

report=$(grep -i "error" logs/app.log | claude -p "归并同类报错,按影响排序" --output-format json)
printf '%s\n' "$report" | jq -r '.result'

两条原则:先看 is_error、再校验收到的结构,最后才取 result;解析失败按错误处理,不要静默变成空字符串。需要边生成边处理时,可以选流式输出,把逐条事件交给下游;只是落盘的话,一次性结果更省心。

脚本里的四条纪律

  1. 看退出码。 成功为零,失败非零。紧跟判断,或在脚本开头设置遇错即停。
  2. 设超时。 外层用 timeout 包住,别让一次卡住的调用拖死整条流水线。
  3. 管权限。 单次模式不等于放开写权限;改文件、跑命令仍受权限设置约束。无人值守时先缩小工作范围,再决定放到多宽。
  4. 记账。 每次调用的耗时与费用写进日志;跑批量前先用一条样本估算总量。

批量处理时逐条循环、逐条检查返回值。前一条失败,就不要继续覆盖后面的产物。要重试就限次数、拉长间隔,别在故障时空转。

一个最小可用的检查脚本

#!/usr/bin/env bash
set -euo pipefail
log="logs/app.log"
out=$(grep -i "error" "$log" | claude -p "归并同类报错,给出三条最优先的修复建议")
printf '%s\n' "$out"

注意 grep 没匹配到内容时退出码非零,配合 set -o pipefail 会让脚本提前结束;要么在 grep 后加 || true,要么把「没有报错」当成正常分支,先判断匹配结果再决定是否调用。

先在只读场景把它跑顺,再考虑加入写文件、发通知这些动作。判断标准很朴素:单独跑十次,结果稳定、退出码可信,才值得固化。

一次处理一批文件:完整脚本

单条命令能跑通,不代表批量任务安全。下面这个脚本处理一个目录里的 Markdown 文件,每个文件单独调用一次,产物写入 out/,任何一份失败都不会拖垮其余文件:

#!/usr/bin/env bash
set -uo pipefail

in_dir="docs"
out_dir="out"
mkdir -p "$out_dir"

failed=0
for f in "$in_dir"/*.md; do
  [ -e "$f" ] || { echo "没有匹配到文件" >&2; exit 1; }
  name=$(basename "$f" .md)
  tmp="$out_dir/$name.txt.part"
  if claude -p "只输出三条要点,每条一行,不加标题和前言" \
       < "$f" > "$tmp"; then
    mv "$tmp" "$out_dir/$name.txt"
    echo "完成: $f"
  else
    rm -f "$tmp"
    echo "失败: $f" >&2
    failed=1
  fi
done

exit "$failed"

几个细节值得照搬:

  • 先写临时文件,成功后再改名,避免下游读到半截结果。
  • 失败计数而不是立刻退出,批处理时你希望知道总共有几份没成功。
  • 没有匹配到文件时明确报错;否则循环体一次都不执行,脚本会「成功」退出。
  • 产物目录与源目录分开,重复运行也不会覆盖原文。

跑之前先拿一份样本试提示词:

claude -p "只输出三条要点,每条一行,不加标题和前言" < docs/示例.md

确认输出形状稳定,再把同一句话放进循环。若每份文件需要不同的指令,就在循环里按文件名分支,不要把所有规则塞进一条超长提示词。

常见故障:现象、原因与处理

现象 为什么 怎么办
管道左边没输出,右边仍返回一段泛泛而谈 上游命令没匹配到内容,管道默认不传递失败状态 先看上游退出码与行数;空输入时直接跳过调用
提示词的要求被素材淹没 标准输入与命令行文字拼成同一段,长素材占了大部分注意力 提示词写具体约束,素材前后加分隔行,内容太长先裁剪
JSON 解析报错或取到空值 输出里混入解释文字,或字段名与当前版本不同 用 JSON 输出模式,先打印整体结构再取字段,并检查错误标记
脚本在无人值守时停住 某一步需要人工确认权限,单次模式也不会自动同意 只读任务先跑;确需写操作时缩小目录范围,并按当前版本配置权限
跑了一夜,账单超出预期 循环次数乘以单次费用,没有先估算 先用一份样本记录耗时和费用,再乘总数;日志里保留每次的用量字段,估算方法见费用估算
长日志让回答只覆盖开头和结尾 输入超过上下文容量,中段被挤出 用 head、grep 或时间窗口先缩小范围,分段处理再汇总

还有三类任务不适合走管道。需要来回追问、逐步改稿的,应该用交互模式;需要对同一个仓库连续做多处修改的,单次调用每次都要重新建立上下文,效率反而低;材料里含密钥、客户隐私或未脱敏数据的,不要直接送进命令行,先脱敏或改用受控环境。

下一节处理另一半问题:任务做到一半,怎么接着上次的上下文继续,见继续最近的对话。

自测

先自己回答,再展开对照;答不上来就回到对应小节。
  1. 01管道内容会替换掉命令行里的提示词吗?看答案

    不会。标准输入和 -p 后面的那句话会拼成同一段输入,所以指令要写全,素材的范围和含义也要交代。

  2. 02为什么在脚本里调用时要先看退出码?看答案

    成功返回零、失败返回非零,这是脚本分流的唯一可靠依据;只看输出文本会把失败当成空结果继续往下跑。

查看 Markdown

涉及的概念

在知识树上

相关动态

全部新闻 →