乐趣区

关于linux:q命令用SQL分析文本文件

原创:打码日记(微信公众号 ID:codelogs),欢送分享,转载请保留出处。

简介

在 Linux 上剖析文本文件时,个别会应用到 grep、sed、awk、sort、uniq 等命令,但这些命令都有肯定的学习老本,而如果是用 SQL 来剖析数据的话,这对宽广后端程序员来说,就要简略很多了。

而 q 命令就是这样一款工具,能够在空白、逗号分隔的文本文件上执行 SQL 运算,十分不便。

装置

# ubuntu 下装置
$ sudo apt install python3-q-text-as-data

# centos 下可下载安装包装置
$ wget https://github.com/harelba/q/releases/download/v3.1.6/q-text-as-data-3.1.6.x86_64.rpm
$ rpm -Uvh q-text-as-data-3.1.6.x86_64.rpm

如果是其它 Linux 发行版,能够参考官网装置文档:http://harelba.github.io/q/#i…。

常见用法

剖析空白分隔文件

默认状况下,q 将文本文件中每一行当作一条数据,应用空白作为字段分隔符。
假如有如下学生列表,要查问出大于 16 岁的学生的 id 与姓名,如下:

$ cat students.txt
id name age sex
1 person1 15 0
2 person2 15 0
3 person3 16 0
4 person4 16 0
5 person5 16 0
6 person6 17 1
7 person7 17 1
8 person8 17 1
9 person9 18 1
10 person10 18 1

# 查问出大于 16 岁的学生的 id 与姓名
# -H : 告知 q 命令第一行是题目行
$ q -H 'select id,name from students.txt where age>16'
6 person6
7 person7
8 person8
9 person9
10 person10

# - O 可使输入后果中带有题目
$ q -H -O 'select id,name from students.txt where age>16'
id name
6 person6
7 person7
8 person8
9 person9
10 person10

如果文件中没有题目行的话,可应用 c1、c2、c3... 来援用字段,如下:

$ cat students.txt
1 person1 15 0
2 person2 15 0
3 person3 16 0
4 person4 16 0
5 person5 16 0
6 person6 17 1
7 person7 17 1
8 person8 17 1
9 person9 18 1
10 person10 18 1

# 查问出大于 16 岁的学生的 id 与姓名
$ q 'select c1,c2 from students.txt where c3>16'
6 person6
7 person7
8 person8
9 person9
10 person10

从规范输出读取数据

q 命令也可间接从规范输出中读取数据,应用 - 作为表名即可,如下:

$ cat students.txt | q -H -O 'select * from - limit 2'
id name age sex
1 person1 15 0
2 person2 15 0

剖析 csv 文件

q 命令默认应用空白作为分隔符,但也能够通过 -d 指定分隔符,这样能够很容易地剖析 csv 文件 (, 分隔)或 tsv 文件 (\t 分隔),如下:

$ cat students.csv
id,name,age,sex
1,person1,15,0
2,person2,15,0
3,person3,16,0
4,person4,16,0
5,person5,16,0
6,person6,17,1
7,person7,17,1
8,person8,17,1
9,person9,18,1
10,person10,18,1

# -d : 指定分隔符
$ q -H -d, 'select count(*) from students.csv where age>16'
5

q 命令还能够自动识别文件中的双引号",这使得字段值中带有逗号的场景也能够很容易解决,如下:

$ cat students.csv
id,name,age,sex
1,"person,lisi",15,0
2,"person,wangwu",15,0
3,person3,16,0
4,person4,16,0
5,person5,16,0
6,person6,17,1
7,person7,17,1
8,person8,17,1
9,person9,18,1
10,person10,18,1

# q 命令可主动将引号内数据读取成一个字段
$ q -H -d, 'select * from students.csv where age=15'
1,"person,lisi",15,0
2,"person,wangwu",15,0

# awk 没有这种机制,字段援用错位,导致查不到数据
$ awk -F, '$3==15{print $0}' students.csv

q 命令也能够很容易地解决最初一列带分隔符的场景,如下:

# ps 输入的最初一列 COMMAND 带有空格
$ ps 1
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     1:28 /sbin/init auto noprompt text

# 如果用 awk,会发现漏掉了空格后的局部
$ ps 1 | awk '{print $5}'
COMMAND
/sbin/init

# q 命令可应用 -c 5 指定列数量,这样最初一列就残缺查出来了
$ ps 1 | q -H -O -c 5 'select COMMAND from -'
COMMAND
"/sbin/init auto noprompt text"

多文件关联查问

SQL 中最弱小的关联查问,q 命令也是能够反对的,如下:

$ cat user.txt
id name
1 zhangsan
2 lisi
3 wangwu
4 pangliu

$ cat score.txt
id score
1 86
2 57
3 92

$ q -H 'select u.id,u.name,s.score from user.txt u left join score.txt s on u.id=s.id'
1 zhangsan 86
2 lisi 57
3 wangwu 92
4 pangliu

其它

q 命令应用了 SQLite 这个嵌入式数据库,运行过程中,q 命令会在 SQLite 中创立长期数据库与表,并将文本数据插入到长期表中,而后 SQL 语句间接执行在这个长期表上。

所以实践上,只有是 SQLite 反对的 SQL 语法,q 命令也反对。

能够通过 -A 查看长期表的表构造,如下:

# 仅查看表构造,SQL 理论不会执行
$ q -H -d, -A 'select * from students.csv'
Table for file: students.csv
  `id` - int
  `name` - text
  `age` - int
  `sex` - int

能够发现,idagesex 字段都是 int 类型,这是 q 命令主动从文本数据中剖析进去的。

往期内容

原来 awk 真是神器啊
Linux 文本命令技巧 (上)
Linux 文本命令技巧(下)
字符编码解惑

退出移动版