csvq 1.18.1 常用 CLI 命令与工具详解
csvq v1.18.1 全部常用命令实测详解:单次查询/导出 flag、交互壳内置命令(ECHO/PRINT/SHOW/SOURCE/RELOAD CONFIG/$外部命令)、事务与文件回写(UPDATE/REPLACE USING/CREATE TABLE AS/ALTER)、游标/预处理/CTE/VIEW/UDF/流程控制、calc/fields/syntax/check-update 子命令与返回码语义
csvq 1.18.1 常用 CLI 命令与工具详解
目标:把 csvq 的命令行用法、交互壳内置命令、事务性文件回写、SQL 编程特性与四个内置子命令逐一实测讲透,全部回显来自 Ubuntu 22.04 + csvq v1.18.1 的真实执行记录。环境搭建见 《Ubuntu 22.04 安装 csvq 1.18.1 指南》,参数含义见 《csvq 1.18.1 配置参数详解》。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(jammy),x86_64;csvq v1.18.1(
csvq version 1.18.1) - 工作目录:
/root/csvdemo(账号 root) - 测试数据:
users.csv(id,name,age,city,salary,joined 六列 5 行)、scores.tsv、products.json、access.ltsv、orders.jsonl、nested.json、fixdata.txt、sjis.csv - 交互壳回显约定:默认提示符为「当前目录 +
>」;存在未提交事务时自动追加(Uncommitted:N);查询结果固定以框线表格渲染
二、前置条件
- csvq 已安装并在 PATH;
/root/csvdemo下已放置上述数据文件(users.csv 内容见选型篇 5.2)。 - 表名含扩展名(带
.)时必须反引号包裹,否则报syntax error: unexpected token "."(实测;交互壳内可省略.csv后缀直接用users)。
三、命令总览
| 类别 | 命令/用法 | 说明 |
|---|---|---|
| 单次查询 | csvq [-f 格式] [-o 文件] "SELECT ..." | 非交互执行,flag 必须在语句前 |
| 脚本执行 | csvq -s script.sql | 顺序执行文件中的多条语句 |
| 交互壳 | csvq(无参) | TTY 专用,支持事务/游标/UDF/内置命令 |
| 内置命令 | ECHO/PRINT/PRINTF/PWD/SOURCE/RELOAD CONFIG/$命令 | 交互壳专用 |
| 自省 | SHOW FLAGS/ENV/RUNINFO/TABLES/FIELDS/CURSORS/FUNCTIONS | 查看状态 |
| 事务 | COMMIT/ROLLBACK | 首条写语句隐式开启事务(BEGIN 非法,见 5.1) |
| 子命令 | calc/fields/syntax/check-update | 独立工具能力 |
四、查询与分析命令
4.1 基础查询与条件过滤
$ csvq "SELECT id, name, city FROM \`users.csv\` WHERE age > 30 ORDER BY salary DESC LIMIT 3"
id,name,city
3,Mildred,Nagoya
1,Louis,Tokyo
4,Harold,Fukuoka
4.2 聚合与分组
$ csvq "SELECT u.city, COUNT(*) AS n, AVG(u.age) AS avg_age FROM \`users.csv\` u GROUP BY u.city ORDER BY n DESC"
city,n,avg_age
Tokyo,1,35
Osaka,1,28
Nagoya,1,42
Fukuoka,1,31
Sapporo,1,26
4.3 跨文件 JOIN(含 TSV/JSON)
$ csvq "SELECT u.name, s.subject, s.score FROM \`users.csv\` u INNER JOIN \`scores.tsv\` s ON u.id = s.user_id WHERE s.score >= 90"
name,subject,score
Louis,math,92
Mildred,english,95
Sophie,science,99
4.4 子查询与 CTE
$ csvq "SELECT name, salary FROM \`users.csv\` WHERE salary > (SELECT AVG(salary) FROM \`users.csv\`)"
name,salary
Louis,5200000
Mildred,6300000
CTE 实测(交互壳内单行):
/root/csvdemo > WITH t AS (SELECT city, AVG(salary) AS avg_sal FROM users GROUP BY city) SELECT * FROM t ORDER BY avg_sal DESC;
+----------+---------+
| city | avg_sal |
+----------+---------+
| Nagoya | 6300000 |
| Tokyo | 5200000 |
| Osaka | 4100000 |
| Fukuoka | 3800000 |
| Sapporo | 3500000 |
+----------+---------+
4.5 窗口函数
$ csvq "SELECT name, city, salary, RANK() OVER (PARTITION BY city ORDER BY salary DESC) AS rk FROM \`users.csv\` LIMIT 3"
name,city,salary,rk
Mildred,Nagoya,6300000,1
Louis,Tokyo,5200000,1
Sean,Osaka,4100000,1
4.6 定长/编码/嵌套 JSON 读取
$ csvq -i FIXED -m '[10,18,25]' "SELECT * FROM \`fixdata.txt\`"
name,city,salary
Louis,Tokyo,5200000
Sean,Osaka,4100000
Mildred,Nagoya,6300000
$ csvq -e SJIS "SELECT * FROM \`sjis.csv\`"
名前,太郎,東京
花子,二郎,大阪
$ csvq -j 'users' "SELECT * FROM \`nested.json\`"
name,tags
Tom,"[""x"",""y""]"
Amy,"[""z""]"
要点:FIXED 的 -m 是累积切割位不是列宽;SJIS 在 AUTO 下也能识别;嵌套对象数组用 -j 指定查询路径(users 与 users{} 实测等价)。
五、文件读写命令(直接改磁盘文件)
⚠️ 警告:csvq 的写语句直接修改源文件。交互壳内有事务缓冲(COMMIT 前不落盘、ROLLBACK 可还原),但非交互单条语句自动提交、无回滚机会——生产文件先
cp备份再操作。
5.1 UPDATE 与 ROLLBACK(交互壳实测)
/root/csvdemo > UPDATE users SET name = 'Mildred-X' WHERE id = 3;
1 record updated on "/root/csvdemo/users.csv".
/root/csvdemo (Uncommitted:1) > ROLLBACK;
Rollback: file "/root/csvdemo/users.csv" is restored.
提示符出现 (Uncommitted:1) 即表示有 1 个文件的改动未落盘;此时 SELECT 读到的是改后值,ROLLBACK 后恢复原值(实测还原为 Mildred)。
⚠️ 注意:csvq 没有
BEGIN语句——实测交互壳执行BEGIN;报[L:1 C:1] syntax error: unexpected token "BEGIN"。事务由首条写语句(UPDATE/INSERT/REPLACE/DELETE/CREATE/ALTER)隐式开启,COMMIT/ROLLBACK 结束;ROLLBACK 后实测文件逐字节还原:
/root/csvdemo > BEGIN;
[L:1 C:1] syntax error: unexpected token "BEGIN"
/root/csvdemo > UPDATE users SET name = 'TmpX' WHERE id = 1;
1 record updated on "/root/csvdemo/users.csv".
/root/csvdemo (Uncommitted:1) > ROLLBACK;
Rollback: file "/root/csvdemo/users.csv" is restored.
/root/csvdemo > SELECT id, name FROM users WHERE id = 1;
+----+--------+
| id | name |
+----+--------+
| 1 | Louis |
+----+--------+
5.2 INSERT / DELETE / COMMIT
/root/csvdemo > INSERT INTO users (id, name, age, city, salary, joined) VALUES (6, 'Taro', 40, 'Kyoto', 4500000, '2023-01-10');
1 record inserted on "/root/csvdemo/users.csv".
/root/csvdemo (Uncommitted:1) > COMMIT;
Commit: file "/root/csvdemo/users.csv" is updated.
/root/csvdemo > DELETE FROM users WHERE id = 6;
1 record deleted on "/root/csvdemo/users.csv".
/root/csvdemo (Uncommitted:1) > COMMIT;
Commit: file "/root/csvdemo/users.csv" is updated.
5.3 REPLACE INTO:必须带 USING 键
普通 REPLACE INTO ... VALUES 实测语法错误——csvq 的 REPLACE 是"按键替换"语法,必须 USING (键列):
/root/csvdemo > REPLACE INTO users (id, name, age, city, salary, joined) VALUES (6, 'Jiro', 44, 'Kobe', 4800000, '2023-02-01');
[L:1 C:58] syntax error: unexpected token "VALUES"
/root/csvdemo > REPLACE INTO users (id, name, age, city, salary, joined) USING (id) VALUES (2, 'Sean-B', 28, 'Osaka', 4300000, '2020-10-15');
1 record replaced on "/root/csvdemo/users.csv".
5.4 CREATE TABLE AS:新文件落盘
/root/csvdemo > CREATE TABLE `backup.csv` AS SELECT id, name FROM users WHERE age > 30;
file "/root/csvdemo/backup.csv" is created.
/root/csvdemo (Uncommitted:1) > COMMIT;
Commit: file "/root/csvdemo/backup.csv" is created.
目标文件名同样受"带点必须反引号"约束:不写反引号报 [L:1 C:20] syntax error: unexpected token "."(实测)。
5.5 ALTER TABLE:加列与改属性
加列的正确语法是 ADD (列名),MySQL 式 ADD COLUMN 列名 实测报错:
/root/csvdemo > ALTER TABLE users ADD COLUMN dept;
[L:1 C:30] syntax error: unexpected token "dept"
/root/csvdemo > ALTER TABLE users ADD (dept);
1 field added on "/root/csvdemo/users.csv".
/root/csvdemo (Uncommitted:1) > COMMIT;
Commit: file "/root/csvdemo/users.csv" is updated.
/root/csvdemo > $head -1 /root/csvdemo/users.csv
id,name,age,city,salary,joined,dept
改文件属性用 SET <属性> TO <值>。大坑实测:ALTER TABLE users SET DELIMITER TO ';'; COMMIT 后文件内容确实按分号重写($head -1 看到 id;name;...),但读侧元数据仍显示 Delimiter: ',',整行退化为单列(Fields: 1. id;name;age;...)——分隔符变更必须配合重新加载/显式 -d ';' 查询,改前务必备份。
六、格式转换命令(-f + -o)
csvq 是顺手的平面文件格式转换器,实测三组:
$ csvq -f JSON -o /root/csvdemo/b2/out_users.json "SELECT id, name, salary FROM \`users.csv\` WHERE age > 30"
$ cat /root/csvdemo/b2/out_users.json
[{"id":"1","name":"Louis","salary":"5200000"},{"id":"3","name":"Mildred","salary":"6300000"},{"id":"4","name":"Harold","salary":"3800000"}]
$ csvq -f CSV "SELECT * FROM \`products.json\`"
sku,name,price
A-100,keyboard,4980
A-200,mouse,1980
B-100,monitor,28900
B-200,headset,7800
$ csvq -f TSV "SELECT time, host, status FROM \`access.ltsv\`"
time host status
2026-11-01T081203+0900 web01 200
2026-11-01T081205+0900 web01 500
要点:-o 导出与管道输出默认格式不同(CSV for pipe / TEXT otherwise);LTSV 值含冒号会被吞(08:12:03 → 081203,见 9.3);-N 去表头、-D '|' 换输出分隔符、-E SJIS 换输出编码均实测可用。
七、交互壳内置命令
7.1 输出与外部命令
/root/csvdemo > ECHO 'csvq echo test';
csvq echo test
/root/csvdemo > PRINT 1 + 2;
3
/root/csvdemo > PRINTF '%s -> %d' USING 'abc', 42;
abc -> 42
/root/csvdemo > PWD;
/root/csvdemo
/root/csvdemo > $echo 'external command';
external command
$ 前缀直接调系统命令(实测 $ls、$head、$sed 均可用),是壳内核实现场的第一工具。
7.2 自省命令
/root/csvdemo > SHOW FLAGS; # 30 个 flag 现值(全表见配置篇)
/root/csvdemo > SHOW ENV; # 宿主环境变量映射(@%PWD/@%HOME/@%PATH...)
/root/csvdemo > SHOW RUNINFO; # @#UNCOMMITTED/@#VERSION/@#WORKING_DIRECTORY 等
/root/csvdemo > SHOW TABLES;
No table is loaded
/root/csvdemo > SHOW FIELDS FROM users;
Fields in users
-----------------------------------------------------
Type: File
Path: /root/csvdemo/users.csv
Format: CSV Delimiter: ',' Enclose All: false
Encoding: UTF8 LineBreak: LF Header: true
Status: Fixed
Fields:
1. id
2. name
3. age
4. city
5. salary
6. joined
/root/csvdemo > SHOW CURSORS;
No cursor is declared
/root/csvdemo > SHOW FUNCTIONS;
Scalar Functions
------------------
add_tax (@p)
7.3 脚本与配置加载
/root/csvdemo > SOURCE '/hostshare/stmts.sql';
+-----+----------+
| seq | name |
+-----+----------+
| 1 | Louis |
...
/root/csvdemo > RELOAD CONFIG;
SOURCE 实测需带引号的绝对路径(裸文件名 SOURCE stmts.sql; 报 unexpected token ";");RELOAD CONFIG; 热加载 csvq_env.json(实测提示符实时变化)。
7.4 变量:@%(环境/会话)与 @#(运行时只读)
/root/csvdemo > SET @%MYVAR TO 'demo-value';
/root/csvdemo > ECHO @%MYVAR;
demo-value
/root/csvdemo > UNSET @%MYVAR;
/root/csvdemo > ECHO @#VERSION;
1.18.1
SQL 会话变量用 VAR(见 8.2),与 @% 环境变量是两套体系。
八、SQL 编程特性(交互壳)
8.1 游标:标识符不带 @,先 VAR 声明目标变量
/root/csvdemo > DECLARE c1 CURSOR FOR SELECT name FROM users WHERE age > 30;
/root/csvdemo > OPEN c1;
/root/csvdemo > VAR @n1;
/root/csvdemo > FETCH c1 INTO @n1;
/root/csvdemo > ECHO @n1;
Louis
/root/csvdemo > FETCH c1 INTO @n1;
/root/csvdemo > ECHO @n1;
Mildred
/root/csvdemo > CLOSE c1;
/root/csvdemo > DISPOSE CURSOR c1;
实测坑:FETCH ... INTO @n1 在变量未声明时报 variable @n1 is undeclared——必须先 VAR @n1;;游标名写 @c 形式直接语法错(DECLARE @c CURSOR 报 unexpected token "CURSOR");WHILE VAR ... IN c2 前忘记 OPEN 报 cursor c2 is closed。
8.2 会话变量与 SELECT INTO
/root/csvdemo > VAR @mx;
/root/csvdemo > SELECT MAX(salary) INTO @mx FROM users;
/root/csvdemo > ECHO @mx;
6300000
/root/csvdemo > VAR @id := 0;
/root/csvdemo > SELECT @id := @id + 1 AS seq, name FROM users;
+-----+----------+
| seq | name |
+-----+----------+
| 1 | Louis |
| 2 | Sean |
...
8.3 预处理语句
/root/csvdemo > PREPARE p1 FROM 'SELECT name, city FROM users WHERE id = ?;';
/root/csvdemo > EXECUTE p1 USING 2;
+------+--------+
| name | city |
+------+--------+
| Sean | Osaka |
+------+--------+
/root/csvdemo > DISPOSE PREPARE p1;
8.4 VIEW 临时表
/root/csvdemo > DECLARE v1 VIEW AS SELECT id, name FROM users WHERE age < 30;
/root/csvdemo > SELECT * FROM v1;
+----+--------+
| id | name |
+----+--------+
| 2 | Sean |
| 5 | Sophie |
+----+--------+
/root/csvdemo > DISPOSE VIEW v1;
8.5 用户自定义函数:参数不能带类型
/root/csvdemo > DECLARE add_tax FUNCTION (@p) AS BEGIN RETURN @p * 1.1; END;
/root/csvdemo > SELECT name, add_tax(salary) AS with_tax FROM users LIMIT 2;
+--------+----------+
| name | with_tax |
+--------+----------+
| Louis | 5720000 |
| Sean | 4510000 |
+--------+----------+
实测两处语法禁区:参数表写类型 (@p INT) 报 unexpected token "INT";函数体内 RETURN CAST(@p * 1.1 AS INT); 报 unexpected token "AS"。
8.6 流程控制:IF / WHILE 必须单行
/root/csvdemo > IF (SELECT COUNT(*) FROM users) > 4 THEN ECHO 'more than 4 users'; ELSE ECHO 'few users'; END IF;
more than 4 users
/root/csvdemo > VAR @i := 0;
/root/csvdemo > WHILE @i < 3 DO ECHO @i; SELECT @i := @i + 1; END WHILE;
0
+--------------+
| @i := @i + 1 |
+--------------+
| 1 |
+--------------+
1
...
跨行书写实测失败:WHILE @i < 3 换行报 unexpected termination(v1.18.1 的 continuous_prompt 不触发续读)。
九、子命令工具与返回码
9.1 csvq fields:查看文件字段
$ csvq fields users.csv
id
name
age
city
salary
joined
9.2 csvq calc:管道单值计算
用法为"stdin 提供数据(列名 c1),参数给表达式":
$ echo 'foo' | csvq calc "base64_encode(c1)"
Zm9v
$ echo 123 | csvq calc "c1 + 100"
223
无 stdin 时报 incorrect usage: STDIN is empty;表达式必须作为恰好 1 个参数传入。
9.3 csvq syntax:打印 SQL 语法
$ csvq syntax select | head -8
Search: select
-------------------------------------------------------------------------
SELECT Statement
select_query
: [<with_clause>] <select_entity> [<order_by_clause>]
[<limit_clause>] [FOR UPDATE]
排障利器:不确定语法时直接查官方文法(如 csvq syntax "replace into" 可看到 USING 子句)。
9.4 csvq check-update:版本检查
$ csvq check-update
The current version 1.18.1 is up to date.
$ echo $?
0
9.5 返回码语义(实测)
| 场景 | rc | 关键回显 |
|---|---|---|
| 正常 | 0 | — |
| 文件不存在 | 16 | [L:1 C:15] file nosuchfile does not exist |
| 语法错误 | 4 | [L:1 C:9] syntax error: unexpected token "BOGUS" |
| 触发显式错误 | 64 | TRIGGER ERROR 'msg' → [L:1 C:1] manual |
| 参数冲突 | 2 | incorrect usage: no argument can be passed when "--source" option is specified |
| csvqrc 非法语句 | 1 | /root/csvdemo/csvqrc [L:1 C:5] @@ROW_LIMIT is an unknown flag |
十、常用操作速查
| 需求 | 命令 |
|---|---|
| 查 CSV | csvq "SELECT * FROM \f.csv` LIMIT 10"` |
| 查 TSV/JSON/JSONL/LTSV | 同上,按扩展名自动识别 |
| 查定长文件 | csvq -i FIXED -m '[10,18,25]' "SELECT * FROM \f.txt`"` |
| 查 SJIS 文件 | csvq -e SJIS "SELECT * FROM \f.csv`"`(AUTO 亦可) |
| 查嵌套 JSON 数组 | csvq -j 'users' "SELECT * FROM \f.json`"` |
| 结果转 JSON 落盘 | csvq -f JSON -o out.json "SELECT ..." |
| 结果转 TSV 到 stdout | csvq -f TSV "SELECT ..." | ... |
| 批量执行脚本 | csvq -s script.sql |
| 改文件(可回滚) | 交互壳 UPDATE/INSERT/DELETE → COMMIT/ROLLBACK |
| 按键替换整行 | REPLACE INTO t (...) USING (键) VALUES (...) |
| 新表落盘 | CREATE TABLE \new.csv` AS SELECT ...` |
| 加列 | ALTER TABLE t ADD (col) |
| 看文件元数据 | SHOW FIELDS FROM t / csvq fields f.csv |
| 看当前参数 | SHOW FLAGS; |
| 查语法 | csvq syntax <关键字> |
| 单值计算进管道 | echo x | csvq calc "expr(c1)" |
十一、常见问题
11.1 表名带点就报 unexpected token "."
csvq 把 . 当语法元素,users.csv 这类文件名一律写 `users.csv`(实测交互壳内可省扩展名直接 users)。
11.2 交互壳脚本管道喂不进去
实测报 input from pipe or redirection cannot be used——交互壳坚持 TTY。批量执行请走 csvq -s,或逐条 csvq "语句"。
11.3 多行 SQL 报 unexpected termination
v1.18.1 交互壳不续读,单条语句必须一行写完;复杂逻辑落 .sql 文件用 SOURCE '/绝对路径'; 或 -s。
11.4 REPLACE INTO 报 unexpected token "VALUES"
csvq 的 REPLACE 必须 USING (键列) 指明匹配键(5.3 实测)。
11.5 改完 UPDATE 文件没变 / 想撤销
未 COMMIT 的改动只在内存缓冲(提示符 (Uncommitted:1)):COMMIT; 落盘、ROLLBACK; 还原(实测文件恢复原文)。非交互模式没有这层缓冲,语句成功即落盘。
11.6 LTSV 时间字段值缺冒号
LTSV 按首个冒号切 key/value,值内冒号被吞(实测 2026-11-01T08:12:03+09:00 导出成 2026-11-01T081203+0900)。含冒号值建议改按 TSV 导入后 SQL 处理。
11.7 找不到 --row-limit / 输出太多刷屏
csvq 无行数限制 flag(--row-limit 报 flag provided but not defined),SQL 里写 LIMIT n;导出场景配 -f CSV -o 文件。