q命令-用SQL分析文字檔案
阿新 • • 發佈:2022-03-26
原創:打碼日記(微信公眾號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
可以發現,id
、age
與sex
欄位都是int型別,這是q命令自動從文字資料中分析出來的。