TextQL 2.0.3 常用 CLI 命令与工具详解
TextQL 2.0.3 的 CLI 命令全景实测:文件名即表名的即席查询、短 SQL、多文件 JOIN、stdin 管道、regexp 过滤、pretty/TSV 导出、save-to 持久化续查、console 打开 SQLite REPL、sqlfile 多语句执行,含 9 类报错实录与返回码
TextQL 2.0.3 常用 CLI 命令与工具详解
目标:把 TextQL 2.0.3 在服务器上最常用的查询、导出、持久化、REPL、管道协作命令按场景逐一实测展开——每条命令给真实回显,每个报错给现象与规避。TextQL 没有子命令体系(无
textql xxx subcmd),全部能力由"参数 + 位置文件"组合驱动,本文即这套组合的实战手册。以下命令与输出均已在 Ubuntu 22.04(x86_64)+ TextQL 2.0.3(master 源码构建)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(jammy),内核 7.0.0-38-generic,架构 x86_64
- TextQL 版本:2.0.3(master 提交
e6545d5构建,含-sqlfile),位于/usr/local/bin/textql - 配套工具:sqlite3 3.37.2(
-save-to续查与-console需要)
$ textql -version
2.0.3
$ sqlite3 --version
3.37.2 2022-01-06 13:25:41 872ba256cbf61d9290b571c0e6d82a20c224ca3ad82971edc46b29818d5dalt1
二、工具概览
TextQL 的执行模型固定为四步:载入(文件/目录/stdin → 内存 SQLite 表)→ 执行(-sql/-sqlfile 的语句按分号顺序跑)→ 输出(stdout/文件,CSV 或框线表)→ 收尾(-save-to 落盘 / -console 开 REPL)。没有交互壳、没有子命令、没有配置文件;表名=文件基名,管道表名=stdin。
textql [-console] [-save-to path] [-output-file path] [-output-dlm delimter]
[-output-header] [-pretty] [-quiet] [-header] [-dlm delimter]
[-sql sql_statements | -sqlfile path] [path ...]
三、前置条件
安装过程见《Ubuntu 22.04 安装 TextQL 2.0.3 指南》。准备测试数据(本文全部示例基于此):
$ mkdir -p /root/textql-lab/multi && cd /root/textql-lab
$ cat > sales.csv <<'EOF'
id,date,region,product,amount,qty
1,2026-01-03,east,WidgetA,120.50,3
2,2026-01-04,east,WidgetB,89.90,1
3,2026-01-05,west,WidgetA,210.00,5
4,2026-02-01,north,WidgetC,55.25,2
5,2026-02-07,west,WidgetB,310.75,7
6,2026-02-11,east,WidgetC,42.00,1
7,2026-03-02,north,WidgetA,180.40,4
8,2026-03-15,west,WidgetC,99.99,3
9,2026-03-21,east,WidgetA,76.20,2
10,2026-03-30,north,WidgetB,145.60,3
EOF
$ cat > regions.csv <<'EOF'
region,country,manager
east,China,Li
west,China,Wang
north,China,Zhao
EOF
$ printf 'ip\tmethod\tpath\tstatus\n10.0.0.5\tGET\t/health\t200\n10.0.0.6\tPOST\t/api/order\t201\n10.0.0.5\tGET\t/index.html\t404\n' > nginx.tsv
$ printf 'name;age;city\nTom;28;SH\nAmy;31;BJ\n' > semi.csv
$ printf '1,apple,3.5\n2,banana,7.25\n3,cherry,12.0\n' > nohdr.csv
$ cp sales.csv multi/t1.csv
$ printf 'a,b\n1,2\n3,4\n' > multi/t2.csv
$ cat > query.sql <<'EOF'
select region, count(*) as cnt, round(sum(amount),2) as total from sales group by region order by total desc;
select 'ALL_DONE' as mark
EOF
$ ls
multi nginx.tsv nohdr.csv query.sql regions.csv sales.csv semi.csv
四、查询命令
4.1 基础查询与限行
-header 让首行作列名,表名取文件基名 sales:
$ textql -sql "select * from sales limit 3" -header sales.csv
1,2026-01-03,east,WidgetA,120.5,3
2,2026-01-04,east,WidgetB,89.9,1
3,2026-01-05,west,WidgetA,210,5
4.2 短 SQL:省略 SELECT / FROM
单表时 FROM 可省、简单查询时 SELECT 可省,最短就是一颗星:
$ textql -sql "*" -header sales.csv | head -4
1,2026-01-03,east,WidgetA,120.5,3
2,2026-01-04,east,WidgetB,89.9,1
3,2026-01-05,west,WidgetA,210,5
4,2026-02-01,north,WidgetC,55.25,2
$ textql -sql "count(*)" sales.csv
11
⚠️ 注意:第二条没带
-header,首行表头也算数据,所以是 11 而不是 10。列名规则与-header的关系见《TextQL 2.0.3 配置参数详解》5.1 节。
4.3 聚合与排序
$ textql -sql "select region, count(*) cnt, round(sum(amount),2) total from sales group by region order by total desc" -header sales.csv
west,3,620.74
north,3,381.25
east,4,328.6
4.4 跨文件 JOIN
命令行并列多个文件,各自成表即可 JOIN:
$ textql -sql "select s.region, r.country, r.manager, round(sum(s.amount),2) total from sales s join regions r on s.region = r.region group by 1,2,3" -header sales.csv regions.csv
east,China,Li,328.6
north,China,Zhao,381.25
west,China,Wang,620.74
文件与目录可以混着给:
$ textql -sql "select count(*) from t1" multi regions.csv
11
4.5 stdin 管道查询
管道数据的表名固定为 stdin(README 写的 pipe 实测报错):
$ cat sales.csv | textql -sql "select region, round(sum(amount),2) from stdin group by region" -header
east,328.6
north,381.25
west,620.74
$ cat sales.csv | textql -sql "select region, sum(amount) from pipe group by region" -header
2026-11-03 04:49:28 no such table: pipe
4.6 表名覆写与非法名拒绝
名字:文件 语法给表起别名;非法字符直接拒绝:
$ textql -sql "select count(*) from orders" "orders:sales.csv"
11
$ textql -sql "select 1" "bad[]name:sales.csv"
2026-11-03 04:50:53 Invalid table name bad[]name
4.7 目录批量载入
目录参数非递归展开为其中每个文件:
$ textql -sql "select count(*) from t1" multi
11
$ textql -sql "select count(*) from t2" multi
3
4.8 类型推断与日期函数
列类型全为 NUMERIC,值类型逐值推断;文本日期列可直接上 strftime:
$ textql -sql "select typeof(amount) amt_t, typeof(date) date_t, typeof(id) id_t from sales limit 1" -header sales.csv
real,text,integer
$ textql -sql "select strftime('%Y-%m', date) month, round(sum(amount),2) total from sales group by month order by month" -header sales.csv
2026-01,420.4
2026-02,408
2026-03,502.19
4.9 regexp 过滤
内置 regexp 操作符,无需扩展库:
$ textql -sql "select id, product from sales where product regexp 'Widget[AB]' and qty > 2" -header sales.csv
1,WidgetA
3,WidgetA
5,WidgetB
7,WidgetA
10,WidgetB
五、输出与导出命令
5.1 列名 + 自定义输出分隔符
-output-header 输出列名,-output-dlm tab 把结果切成 TSV:
$ textql -sql "select product, sum(qty) q from sales group by product" -header -output-header -output-dlm tab sales.csv
product q
WidgetA 14
WidgetB 11
WidgetC 6
5.2 框线表(-pretty)
$ textql -sql "select product, sum(qty) q from sales group by product" -header -pretty sales.csv
+---------+----+
| WidgetA | 14 |
| WidgetB | 11 |
| WidgetC | 6 |
+---------+----+
5.3 结果落盘(-output-file)
$ textql -sql "select region, round(sum(amount),2) total from sales group by region" -header -output-file out_region.csv sales.csv
$ cat out_region.csv
east,328.6
north,381.25
west,620.74
框线表同样可落盘:
$ textql -sql "select product, sum(qty) q from sales group by product" -header -pretty -output-file pretty_out.txt sales.csv
$ cat pretty_out.txt
+---------+----+
| WidgetA | 14 |
| WidgetB | 11 |
| WidgetC | 6 |
+---------+----+
5.4 导出 TSV 供下游管道
$ textql -sql "select region, round(sum(amount),2) total from sales group by region" -header -output-header -output-dlm tab -output-file region_total.tsv sales.csv
$ cat -A region_total.tsv | head -4
region^Itotal$
east^I328.6$
north^I381.25$
west^I620.74$
^I 即制表符,$ 为行尾标记(cat -A 显示),确认导出的是标准 TSV。
六、持久化与 REPL 命令
6.1 -save-to 落库 + sqlite3 续查
$ textql -sql "select count(*) from sales" -header -save-to salesdb2.sqlite sales.csv
10
$ sqlite3 salesdb2.sqlite ".schema sales"
CREATE TABLE [sales] ([id] NUMERIC, [date] NUMERIC, [region] NUMERIC, [product] NUMERIC, [amount] NUMERIC, [qty] NUMERIC);
$ sqlite3 salesdb2.sqlite "select region, round(sum(amount),2) from sales group by region order by 2 desc;"
west|620.74
north|381.25
east|328.6
⚠️ 注意:落库忘带
-header时列名变c0..c5,sqlite3 按业务列名查询实测报Error: in prepare, no such column: amount (1)。
6.2 -console 打开官方 SQLite REPL
-console 要求文件输入(拒绝管道)且 PATH 有 sqlite3。交互会话实测(输入行为用户键入):
$ textql -console -sql "select 1" sales.csv
1
1
...(10 行数据逐行输出 select 1 的结果)
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .tables
sales
sqlite> select count(*) from sales;
11
sqlite> .quit
(输出节选(实测首尾):select 1 未带 -header,11 行数据各出一个 1。)
管道场景直接拒绝:
$ cat sales.csv | textql -console -sql "select 1"
2026-11-03 04:49:28 Can not open console with pipe input, read a file instead
6.3 -console + -save-to:REPL 直接打开持久库
带 -save-to 时 REPL 打开的就是落盘文件本身,退出后库还在:
$ textql -console -header -sql "select 1" -save-to condb2.sqlite sales.csv
(REPL 内)
sqlite> .tables
sales
sqlite> select count(*) from sales;
10
sqlite> .quit
$ ls -la condb2.sqlite
-rw-r--r-- 1 root root 8192 Nov 3 04:50 condb2.sqlite
$ sqlite3 condb2.sqlite "select count(*) from sales;"
10
-output-header 会透传给 sqlite3(等价 sqlite3 -header)。
七、SQL 文件执行(-sqlfile)
7.1 多语句顺序执行
$ textql -sqlfile query.sql -header sales.csv regions.csv
west,3,620.74
north,3,381.25
east,4,328.6
ALL_DONE
ALL_DONE
ALL_DONE
ALL_DONE
ALL_DONE
ALL_DONE
ALL_DONE
ALL_DONE
ALL_DONE
ALL_DONE
第二条语句 select 'ALL_DONE' as mark 无 FROM,自动注入首表逐行执行(10 行数据出 10 行 ALL_DONE)。
7.2 引号内分号不被误拆
-sql 按分号拆语句,但引号内的分号有专门合并处理:
$ textql -sql "select 'a;b' as s; select count(*) as n from sales" sales.csv
a;b
a;b
...(11 行)
11
(输出节选(实测首尾):a;b 逐行输出 11 次后接 11。)
⚠️ 注意:
-sqlfile指向不存在的文件时,程序只打印内存指针0xc000099f40而非错误说明(未修复缺陷);-sql与-sqlfile同时给时-sql优先。参数级细节见《TextQL 2.0.3 配置参数详解》5.2 节。
八、管道链实战
上游先过滤、TextQL 只做聚合,是它在 shell 管道中最典型的用法:
$ grep -v north sales.csv | textql -sql "select region, count(*) from stdin group by region" -header
east,4
west,3
九、返回码(实测)
| 场景 | 命令 | 退出码 |
|---|---|---|
| 查询成功 | textql -sql "count(*)" sales.csv | 0 |
| 表不存在 | textql -sql "select * from nosuch" sales.csv | 1 |
| 文件不存在 | textql -sql "select 1" /nonexistent.csv | 1 |
| 单引号不配对 | textql -sql "select 'unbalanced from sales" sales.csv | 1 |
-version | textql -version | 0 |
脚本中用 if ! textql ...; then 即可捕获失败;错误信息走 stderr、带 2026-11-03 04:49:28 式时间戳前缀。
十、常用操作速查
| 需求 | 命令骨架 |
|---|---|
| 查 CSV | textql -header -sql "select ... from 表名 [where/group by]" f.csv |
| 最短全表 | textql -sql "*" -header f.csv |
| 查 TSV | textql -header -dlm tab -sql "..." f.tsv |
| 查分号分隔 | textql -header -dlm 0x3b -sql "..." f.csv |
| 管道聚合 | ... | textql -header -sql "select ... from stdin" |
| 多表 JOIN | textql -header -sql "select ... from a join b ..." a.csv b.csv |
| 目录批载 | textql -sql "..." dir/(非递归,每文件一表) |
| 起别名 | textql -sql "..." "orders:sales.csv" |
| 导出报表 | 加 -output-header -output-file rpt.csv |
| 人读表格 | 加 -pretty |
| 落 SQLite | textql -header -save-to x.sqlite -sql "..." f.csv |
| 进 REPL | textql -header -console -sql "select 1" f.csv(需 sqlite3) |
| 跑 SQL 文件 | textql -header -sqlfile q.sql f.csv |
| 静默 | 加 -quiet |
十一、常见问题
11.1 SQL 结尾"分号+换行"导致无限刷屏
实测 8 秒输出 73 MB,timeout 杀掉。规避:-sql 结尾不带分号(多语句中间的分号正常)。这是停更项目未修复的最危险缺陷。
11.2 报错只有一串 0xc000045ef0 指针
无 -sql/-sqlfile 或 -sqlfile 文件不存在时打印 *error 指针(log.Fatalln(*error) 缺陷)。补上 SQL 参数/检查文件路径。
11.3 管道里查不到 pipe 表
管道表名是 stdin(README 示例错误,实测 no such table: pipe)。
11.4 count(*) 比实际行数多 1
忘带 -header:首行表头被当数据、列名成 c0..cN。带上 -header 重跑。
11.5 -console 起不来
两种报错:Can not open console with pipe input, read a file instead(管道输入被拒,改用文件);Console requested but unable to locate \sqlite3` program on $PATH(装 sqlite3:apt-get install -y sqlite3`)。
11.6 -save-to 的库在 sqlite3 里查不到业务列名
建库时没带 -header,列名是 c0..c5(实测报 no such column: amount)。带 -header 重建。
11.7 表名覆写报 Invalid table name
名字:文件 的"名字"含 [] 等非法字符(实测 bad[]name 被拒)。改用字母/数字/下划线。
11.8 单引号不配对直接退出
String contains odd number of "'(Single Quotes)"——整条 SQL 引号计数为奇数即拒,检查转义。
11.9 文件不存在
open /nonexistent.csv: no such file or directory(带时间戳、退出码 1),目录路径同理。
十二、参考链接
- 官方仓库与 README 示例:https://github.com/dinedal/textql
- man 手册:https://github.com/dinedal/textql/blob/master/man/textql.1.ronn
- SQLite 日期函数:https://www.sqlite.org/lang_datefunc.html
- 参数逐项说明:《TextQL 2.0.3 配置参数详解》
- 安装与构建:《Ubuntu 22.04 安装 TextQL 2.0.3 指南》
- 选型背景:《TextQL 介绍与选型指南》