← Back to skills
extension
Category: Data & AnalyticsNo API key required

miller - 命名索引数据处理器

基于 Miller (johnkerl/miller) 的命名索引数据处理技能,像 awk/sed/cut/join/sort 一样按列名操作 CSV/TSV/JSON/JSONL,流式处理常数内存

personAuthor: user_8170ea13hubcommunity

miller - 命名索引数据处理器

技能脚本入口

本技能附带两套等价包装脚本(Unix .sh + Windows PowerShell .ps1),提供友好子命令入口与安装自检,免去记忆原始参数。

macOS / Linux(bash):

bash scripts/miller-skill.sh <subcommand> [args...]
# 查看完整用法与示例
bash scripts/miller-skill.sh help

Windows(PowerShell):

.\scripts\miller-skill.ps1 <subcommand> [args...]
# 若被执行策略拦截,用下面这种调用绕过:
powershell -ExecutionPolicy Bypass -File scripts\miller-skill.ps1 <subcommand> [args...]

可用子命令: convert、cut、rename、reorder、put、filter、sort、join、reshape、uniq、sample、head、tail、count

脚本选择规则: macOS / Linux 用 .sh;Windows 用 .ps1。两者子命令完全一致。

脚本仅作便捷封装,最终调用系统的 miller 二进制;运行前请确保已安装对应工具(安装方式见下文各节)。说明:SkillHub 不支持 .cmd / .bat 文件类型,故不附带 Windows cmd 版;无 PowerShell 的环境可用 Git Bash 运行 .sh 版。个别依赖 Unix 管道工具的子命令(如 gron 的 sed / fzf)在 Windows 下建议用 Git Bash 运行 .sh 版。

这是什么

Miller (mlr) (johnkerl/miller, 8.1k ⭐) 是面向 命名索引数据 (CSV、TSV、JSON、JSONL、DKVP) 的类 awk/sed/cut/join/sort 工具。核心优势:按列名而非位置操作、流式处理 (常数内存)、格式保真转换、单二进制 (C 语言,极快)。

  • GitHub: https://github.com/johnkerl/miller
  • 文档: https://miller.readthedocs.io/
  • 适合:ETL 管道、日志处理、数据清洗、格式转换、流式聚合

何时使用我

当用户出现以下意图时加载此技能:

  • "miller"、"mlr 命令"、"处理 csv/json 按列名"
  • "awk 但按列名"、"sed 但按字段名"
  • "流式处理大文件"、"常数内存处理 GB 级数据"
  • "CSV 转 JSON"、"JSON 转 CSV"、"TSV 转 JSONL" 等格式互转
  • "按字段名切片/重排/重命名/计算新列"
  • "分组聚合 (group-by)"、"多键连接 (join)"
  • "正则提取/替换字段值"
  • "数据清洗管道"、"ETL 脚本"

核心能力

1. 格式转换 (保真、流式)

# CSV -> JSON (数组)
mlr --csv --json cat data.csv > data.json

# CSV -> JSON Lines (流式,大文件首选)
mlr --csv --jsonl cat data.csv > data.jsonl

# JSON -> CSV
mlr --json --csv cat data.json > data.csv

# TSV -> JSON
mlr --tsv --json cat data.tsv > data.json

# DKVP (键值对格式) 互转
mlr --dkvp --csv cat data.dkvp > data.csv

# 自动检测格式 (大多数情况)
mlr --icsv --ojson cat data.csv > data.json

2. 列操作 (按名而非位置)

# 选择列 (保留顺序)
mlr --csv cut -f name,age,email data.csv

# 排除列
mlr --csv cut -x -f ssn,password data.csv

# 重排列顺序
mlr --csv cut -f email,name,age data.csv

# 重命名列
mlr --csv rename old_name,new_name data.csv
mlr --csv rename 'first_name,given_name;last_name,surname' data.csv

# 移动列位置
mlr --csv reorder -f id,name,* data.csv  # id,name 在前,其余保持
mlr --csv reorder -e -f ssn data.csv     # ssn 移到最后

3. 计算新列 (put/filter)

# 算术表达式
mlr --csv put '$total = $price * $qty' data.csv

# 字符串操作
mlr --csv put '$full = $first . " " . $last' data.csv
mlr --csv put '$email_domain = gsub($email, ".*@", "")' data.csv

# 条件表达式
mlr --csv put '$tier = if($amount > 1000, "premium", "standard")' data.csv

# 日期时间
mlr --csv put '$days_old = (now() - strptime($created, "%Y-%m-%d")) / (24*3600)' data.csv

# 正则提取
mlr --csv put '$domain = regex_replace($url, "https?://([^/]+).*", "\\1")' data.csv

# 多语句 (分号分隔)
mlr --csv put '
  $ratio = $sales / $target;
  $status = if($ratio >= 1, "met", "missed")
' data.csv

4. 行过滤 (filter)

# 简单条件
mlr --csv filter '$status == "active"' data.csv

# 复合条件
mlr --csv filter '$age >= 18 && $country == "US"' data.csv

# 正则匹配
mlr --csv filter '$email =~ "@gmail\\.com$"' data.csv

# 数值范围
mlr --csv filter '$score >= 60 && $score <= 100' data.csv

# 空值检查
mlr --csv filter 'is_present($email) && $email != ""' data.csv

# 采样 (伯努利/水库)
mlr --csv sample -k 100 data.csv          # 固定 100 行
mlr --csv sample -p 0.1 data.csv          # 10% 概率

5. 排序

# 单列排序
mlr --csv sort -f name data.csv

# 多列排序
mlr --csv sort -f department, -nr salary data.csv  # 部门升序,薪资降序

# 自然排序 (版本号等)
mlr --csv sort -n version data.csv

6. 分组聚合 (stats1/stats2)

# 单键分组聚合
mlr --csv stats1 -a sum,mean,count -f amount -g category data.csv

# 多键分组
mlr --csv stats1 -a min,max,mean -f price -g region,product data.csv

# 多字段聚合
mlr --csv stats1 -a sum,count -f revenue,quantity -g year,month data.csv

# 统计所有数值列
mlr --csv stats1 -a sum,mean,stddev,min,max data.csv

# 计数去重
mlr --csv stats1 -a count -f * -g category data.csv

7. 连接 (join)

# 内连接 (默认)
mlr --csv join -j id -l users.csv -r orders.csv

# 左连接
mlr --csv join -j id --ul users.csv --ur orders.csv

# 多键连接
mlr --csv join -j "user_id,date" -l daily.csv -r monthly.csv

# 字段重命名避免冲突
mlr --csv join -j id -l users.csv -r orders.csv --prefix r_

8. 重塑 (reshape)

# 宽表 -> 长表 (melt)
mlr --csv reshape -r "^qtr" -o item,value data.csv
# 输入: id,qtr1,qtr2,qtr3,qtr4
# 输出: id,item,value  (item=qtr1/qtr2...)

# 长表 -> 宽表 (pivot)
mlr --csv reshape -s item,value data.csv
# 输入: id,item,value
# 输出: id,qtr1,qtr2,qtr3,qtr4

9. 去重与唯一化

# 去重 (全行)
mlr --csv uniq data.csv

# 按键去重 (保留首行)
mlr --csv uniq -g id data.csv

# 计数去重
mlr --csv uniq -c data.csv

10. 正则提取/替换 (gsub/regex_replace)

# 字段级替换
mlr --csv put '$phone = gsub($phone, "[^0-9]", "")' data.csv

# 全记录替换 (sed 风格)
mlr --csv put -q 'for (k, v in $*) { $[k] = gsub(v, "old", "new") }' data.csv

# 正则捕获组提取新列
mlr --csv put '$year = regex_replace($date, "(\\d{4})-\\d{2}-\\d{2}", "\\1")' data.csv

典型工作流示例

场景 1:日志 ETL 管道 (流式,常数内存)

# 1. JSON Lines 日志 -> CSV,提取字段、过滤、计算
cat app.log.jsonl | \
mlr --jsonl --csv \
  cut -f timestamp,level,service,message,latency_ms \
  then filter '$level == "ERROR" || $latency_ms > 1000' \
  then put '$date = strftime(strptime($timestamp, "%Y-%m-%dT%H:%M:%S"), "%Y-%m-%d")' \
  then stats1 -a count,mean -f latency_ms -g date,service \
  > daily_error_latency.csv

场景 2:多源数据标准化合并

# 1. 统一字段名
mlr --csv rename 'user_id,id;full_name,name' source1.csv > s1.csv
mlr --csv rename 'customer_id,id;customer_name,name' source2.csv > s2.csv

# 2. 统一格式为 JSONL
mlr --csv --jsonl cat s1.csv > s1.jsonl
mlr --csv --jsonl cat s2.csv > s2.jsonl

# 3. 合并去重
cat s1.jsonl s2.jsonl | mlr --jsonl uniq -g id > merged.jsonl

# 4. 转回 CSV 供下游
mlr --jsonl --csv cat merged.jsonl > final.csv

场景 3:销售数据分组分析

# 1. 按区域+产品聚合
mlr --csv stats1 \
  -a sum,mean,count,min,max \
  -f revenue,units \
  -g region,product \
  sales.csv | \
mlr --csv sort -f region,-nr sum_revenue > regional_summary.csv

# 2. 算占比
mlr --csv put '
  $total = sum_revenue;
  $pct = $sum_revenue / $total * 100
' regional_summary.csv > regional_with_pct.csv

场景 4:宽表长表互转 (报表 <-> 分析)

# 月度列 -> 长表 (便于绘图/透视)
mlr --csv reshape -r "^month_" -o month,value wide_report.csv > long_data.csv

# 长表 -> 宽表 (生成报表)
mlr --csv reshape -s month,value long_data.csv > wide_report.csv

场景 5:数据清洗标准化

mlr --csv \
  cut -x -f internal_id,debug_flag \
  then rename 'cust_name,name;cust_email,email' \
  then put '
    $email = lower($email);
    $phone = gsub($phone, "[^0-9]", "");
    $created = strftime(strptime($created, "%m/%d/%Y"), "%Y-%m-%d")
  ' \
  then filter 'is_present($email) && $email != ""' \
  then sort -f created \
  dirty.csv > clean.csv

场景 6:JSON/JSONL 处理 (配合 jq)

# JSON 数组 -> JSONL (流式)
mlr --json --jsonl cat data.json > data.jsonl

# JSONL 处理后 -> JSON 数组
mlr --jsonl --json cat processed.jsonl > output.json

# 复杂 JSON 提取 (用 put 的递归能力)
mlr --jsonl put '$user_name = $user.profile.name' events.jsonl

常用动词速查表

| 动词 | 说明 | 关键参数 | |------|------|----------| | cat | 格式转换/透传 | --icsv --ojson 等 | | cut | 选列/排除列 | -f fields, -x 排除 | | rename | 重命名列 | old,new;... | | reorder | 调整列序 | -f, -e 移到末尾 | | put | 计算新列/修改 | DSL 表达式 | | filter | 行过滤 | DSL 条件表达式 | | sort | 排序 | -f, -r 降序, -n 自然序 | | stats1 | 分组聚合 | -a 聚合函数, -f 字段, -g 分组键 | | stats2 | 两两列统计 | 相关性等 | | join | 连接 | -j 键, -l/-r 左/右文件 | | reshape | 宽长互转 | -r 正则, -s 源字段 | | uniq | 去重 | -g 分组键, -c 计数 | | sample | 采样 | -k 固定数, -p 概率 | | head / tail | 头/尾行 | -n 行数 | | count | 计数 | 同 wc -l 但识别格式 | | template | 模板输出 | 自定义格式 |

DSL 表达式速查

# 变量引用
$field_name          # 当前记录字段
$*                   # 所有字段 (迭代用)

# 运算符
+ - * / // %         # 算术 (// 整除)
== != < > <= >=      # 比较
=~ !~                # 正则匹配/不匹配
&& \|\| !            # 逻辑
.                    # 字符串拼接
? :                  # 三元条件

# 内置函数
now()                # 当前时间戳
strptime(s, fmt)     # 解析时间
strftime(ts, fmt)    # 格式化时间
gsub(s, pat, repl)   # 全局替换
regex_replace(s, pat, repl)  # 正则替换 (支持捕获组)
split(s, sep)        # 分割字符串
join(arr, sep)       # 数组连接
length(s/arr)        # 长度
is_present(v)        # 非空检查
is_null(v)           # 空检查
abs(x)               # 绝对值
sqrt(x)              # 平方根
log(x)               # 自然对数
exp(x)               # 指数
floor/ceil/round     # 取整

安装方式

# macOS (Homebrew)
brew install miller

# Linux (包管理器)
apt install miller       # Debian/Ubuntu
dnf install miller       # Fedora/RHEL
pacman -S miller         # Arch
apk add miller           # Alpine

# 二进制下载 (GitHub Releases)
# 单文件,无依赖,解压即用

# Docker
docker run --rm -v "${PWD}":/data johnkerl/miller mlr --csv cat data.csv

性能特性

| 特性 | 说明 | |------|------| | 流式处理 | 常数内存 (O(1)),不读全文件 | | 并行度 | 单线程,但 I/O 与计算重叠 | | 格式支持 | CSV/TSV/JSON/JSONL/DKVP/PPrint/XTAB | | 压缩支持 | 透明读写 .gz/.bz2/.zst (自动检测) | | 大文件 | 100GB+ 测试通过 |

故障排查

| 问题 | 解决方案 | |------|----------| | "command not found: mlr" | brew install miller 或下载二进制 | | 字段名有空格/特殊字符 | 用反引号: $'first name' 或 $["first name"] | | JSON 输入非数组 | 用 --jsonl 逐行处理,或 mlr --json --jsonl cat 转换 | | 内存仍高 | 检查是否用了 sort/join/stats1 (需物化),改用流式动词 | | 日期解析失败 | 确认格式字符串匹配,用 strptime 严格模式 | | 正则不生效 | Miller 正则用 RE2 语法,非 PCRE,避免前瞻/后顾 |

相关技能

  • xsv - 索引加速 CSV 统计/切片/连接 (随机访问快)
  • visidata - 交互式电子表格 (可视化探索)
  • dasel - 统一选择器跨格式查询
  • yq - YAML/JSON/XML/CSV 互转与更新
  • sqlite-utils - 复杂 SQL 查询 (导入 SQLite 后)
  • gron - JSON 扁平化 (配合 mlr 处理嵌套)
  • rq - 10+ 格式专用转换器

技能版本: 1.0.0 | 作者: asdw741111 | 适用平台: OpenCode, Claude Code, Cursor, Codex CLI, Windsurf, Gemini CLI