1. 程式人生 > 其它 >q命令-用SQL分析文字檔案

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/#installation。

常見用法

分析空白分隔檔案

預設情況下,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文字命令技巧(下)
字元編碼解惑