9个不稳定版本 (4个破坏性更新)
0.10.0 | 2021年7月2日 |
---|---|
0.9.1 | 2021年6月28日 |
0.8.2 | 2020年8月29日 |
0.7.2 | 2020年5月3日 |
0.6.2 | 2019年10月21日 |
#688 in 文本处理
每月26次下载
150KB
3K SLoC
csv-groupby
gb
一个命令,可以对分隔文件或任意文本行执行类似SQL的"分组"操作
gb是一个命令,它接受分隔数据(如CSV文件)或文本行(如日志文件),并在该数据上模拟SQL-select-group-by。这是部分受xsv和停止编写相同的perl单行脚本以分析大型日志文件的需求的启发。
它通过在行边界点上"切片"数据块并将这些行偶数块转发到多个解析线程来非常快速地完成这项工作。当提供文件列表作为数据源时,还有多个IO线程。
- 快速 - 在快速的多核机器上,500MB/s到2GB/s的处理速度并不罕见
- 可以执行具有总和、计数、计数唯一、平均、最小值和最大值的分组操作
- 可以使用正则表达式处理CSV文件或文本
- 将文件或stdin作为数据源处理
- csv文件
- 使用正则表达式模式处理文本/日志,其中子组映射到字段位置
- 文件会即时解压缩(如.zst、.gz、.xz等)
- 递归--walk目录树并筛选出您想要的文件
- 可以使用正则表达式过滤/解析文件名(-p),其中子组变为字段。
- 分隔输出或"对齐"表格输出
如何使用
您可以通过列号识别字段。
这些可以是"键"或分组的一部分,一个聚合(平均或总和),或计数唯一。
您可以针对每种类型的字段(包括键字段)使用单到多字段。使用-A选项为这些数字字段提供在输出中使用的"名称"。
csv文件的摘要
使用从以下来源获取的一些航空公司飞行数据:http://stat-computing.org/dataexpo/2009/2008.csv.bz2
请注意,这里的数据略有截断,并且从CSV转换为可读的格式。
1 2 3 4 5 6 7 8 9
Year Month DayofMonth DayOfWeek DepTime CRSDepTime ArrTime CRSArrTime UniqueCarrier ...
2008 1 3 4 2003 1955 2211 2225 WN ...
2008 1 3 4 754 735 1002 1000 WN ...
2008 1 3 4 628 620 804 750 WN ...
2008 1 3 4 926 930 1054 1100 WN ...
2008 1 3 4 1829 1755 1959 1925 WN ...
2008 1 3 4 1940 1915 2121 2110 WN ...
2008 1 3 4 1937 1830 2037 1940 WN ...
2008 1 3 4 1039 1040 1132 1150 WN ...
2008 1 3 4 617 615 652 650 WN ...
....
运行命令
gb -f 2008.csv -k 2,9 -s 14 --skip_header -c | head -10
此命令如何对应于SQL
select Month, UniqueCarrier, count(*), sum(AirTime) from csv group by Month, UniqueCarrier
^ ^ ^
| | |
-k 2, 9 -s 14
这里是部分输出
k:2 | k:9 | count | s:14 | a:14
-----+-----+--------+---------+--------------------
1 | 9E | 22840 | 1539652 | 71.22412915760744
1 | AA | 52390 | 7317245 | 144.5524496246543
1 | AQ | 4026 | 247200 | 61.830915457728864
1 | AS | 12724 | 1587637 | 129.23378103378104
1 | B6 | 16441 | 2477670 | 152.93315227455096
1 | CO | 25168 | 3878167 | 155.51858683883387
1 | DL | 38241 | 4812768 | 130.22967853663818
1 | EV | 23106 | 1584233 | 72.21739526826822
....
另一个示例,用于确定航空公司使用的飞机数量和在空中花费的时间。
select Carrier, count(*), sum(AirTime), count(distinct TailNum), sum(AirTime) average(AirTime) from csv
group by Carrier
以下命令模拟了这一过程
gb -f ~/dl/2008.csv -k 9 -s 14 -u 11 -s 14 -a 14 --skip_header
输出
请注意,列的输出顺序与字段选项的顺序不对应。它固定为键、计数、总和、平均值和唯一值。
k:9 | count | s:14 | s:14 | a:14 | u:11
-----|---------|-----------|-----------|--------------------|------
9E | 262109 | 18080077 | 18080077 | 71.11840692300127 | 162
AA | 604655 | 82989937 | 82989937 | 141.8001178963196 | 656
AQ | 7797 | 479581 | 479581 | 61.889405084527034 | 21
AS | 151045 | 19569900 | 19569900 | 131.83977040764768 | 126
B6 | 196018 | 28849406 | 28849406 | 150.22524356777978 | 154
CO | 298342 | 45784515 | 45784515 | 155.86589297447088 | 378
...
任意文本的摘要
使用正则表达式子组作为数据字段。
或者,您可以使用正则表达式(见-r选项)对捕获子组的行进行操作,这些字段索引与子组对应。这对于像csv这样的非结构化数据很有用,例如日志文件等。
此示例将从mayapp日志文件中提取日期,并根据该行的前5到40个字符对ERROR进行总结。
这是使用文件路径作为报告一部分的示例。
gb --walk /some/log/directory -p 'myapp.*(2019-\d\d-\d\d).log' -r '.*ERROR(.{5,40}).*' -k 1,2
这里使用1和2的子组来创建由日志文件名中的日期和日志文件中ERROR字符串后面的文本组成的复合键。
测试RE模式
如果您想测试一行文本和您的正则表达式之间的交互,请使用选项-R "一些正则表达式" 和 -L "一行文本" 来获取gb将找到的子组。
帮助 gb -h
csv-groupby ver: 0.8.2 rev: 194704d date: 2020-08-29
Execute a sql-like group-by on arbitrary text or csv files. Field indices start at 1.
Note that -l, -f, and -i define where data comes from. If none of these options is given then it default to reading
stdin.
USAGE:
gb [FLAGS] [OPTIONS]
FLAGS:
-c, --csv_output Write delimited output
-v Verbosity - use more than one v for greater detail
--skip_header Skip the first (header) line
--no_record_count Do not write records
--noop_proc Do no real work - no parsing - for testing
-i Read a list of files to parse from stdin
--stats Write stats after processing
--no_output do not write summary output
--recycle_io_blocks_disable disable reusing memory io blocks
--disable_key_sort disables the key sort
-E, --print_examples Prints example usage scenarious - extra help
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-R, --test_re <testre> One-off test of a regex
-L, --test_line <testline>... Line(s) of text to test with -R option instead of stdin
-k, --key_fields <keyfield>... Fields that will act as group by keys
-u, --unique_values <uniquefield>... Fields to count distinct
-D, --write_distros <writedistros>... write unique value distro with -u option
--write_distros_upper <writedistrosupper> number highest value x count [default: 5]
--write_distros_bottom <writedistrobottom> number lowest value x count [default: 2]
-s, --sum_values <sumfield>... Sum fields as float64s
-a, --avg_values <avg_fields>... Average fields
-x, --max_nums <max_num_fields>... Max fields as float64s
-n, --min_nums <min_num_fields>... Min fieldss as float64
-X, --max_strings <max_str_fields>... Max fields as string
-N, --min_strings <min_str_fields>... Min fields as string
-A, --field-aliases <field_aliases>... Alias the field positions to meaningful names
-r, --regex <re-str>... Regex mode regular expression to parse fields
-p, --path_re <re-path> Match path on files and get fields from sub groups
--re_line_contains <re-line-contains> Grep lines that must contain a string
-d, --input_delimiter <delimiter> Delimiter if in csv mode [default: ,]
-q, --quote <quote> csv quote character
-e, --escape <escape> csv escape character
-C, --comment <comment> csv mode comment character
-o, --output_delimiter <outputdelimiter> Output delimiter for written summaries [default: ,]
--empty_string <empty> Empty string substitution [default: ]
-t, --parse_threads <parse-threads> Number of parser threads [default: 12]
-I, --io_threads <io-threads> Number of IO threads [default: 6]
--queue_size <thread-qsize> Queue length of blocks between threads [default: 48]
--path_qsize <path-qsize> Queue length of paths to IO slicer threads [default: 0]
--io_block_size <io-block-size> IO block size - 0 use default [default: 0]
--q_block_size <q-block-size> Block size between IO thread and worker [default: 256K]
-l <file_list> A file containing a list of input files
-f <file>... List of input files
-w, --walk <walk> recursively walk a tree of files to parse
--null_write <nullstring> String to use for NULL fields [default: NULL]
待办/想法
--where 1:<re>
--where_not 1:<re>
--tail &| --head
--count_ge <num>
--count_le
~--sort_count_desc
--sort_count_asc
- 修复-i以也支持-p选项
已修复
- 更好的README - 有时更多并不是更好
- 更丰富的单元测试
- 哦,musl,你在哪里?为什么你的分配那么糟糕....
- 更多聚合:最小值、最大值、空计数、数量计数、零计数
- 平均值和总和已完成
- 对于字符串和数字的最大值和最小值已完成
- 在输出之前对混合键字段进行更快的排序
- 对于csv输出模式,输出更快
更快,但还不是最快
- 对多行re模式做更多工作 - 还不确定它应该如何真正工作
这确实起作用了,我已经在格式良好的xml上使用过它,但还不确定它是否会成为一个东西。
- 扁平模式 - 没有摘要,只是将找到的X个字段写入输出 - 类似于s/()..()..()/$1,$2,$3,.../;
- 使用RE查找/搜索进行匹配而不是行边界接口?
依赖关系
~20–34MB
~522K SLoC