我有一个关于用awk
解析数据的以下问题,它有效,但看起来效率不高,可以在我提出这些观点上改进。
将不胜感激对此的任何建议和帮助。
- 场景一:
原始数据:
# dmesg | awk '/blk_update_request/{ if ($7 =="sector") print $0}' | head -5
[14740442.054675] blk_update_request: I/O error, dev sde, sector 3618747392
[14740442.055693] blk_update_request: I/O error, dev sde, sector 3618746368
[14740442.056807] blk_update_request: I/O error, dev sde, sector 3618745344
[14740442.057927] blk_update_request: I/O error, dev sde, sector 3618744320
[14740442.059074] blk_update_request: I/O error, dev sde, sector 3618743296
试验:
# dmesg | awk '/blk_update_request/{ if ($7 =="sector") print $6}'| cut -d, -f1|head -5
sde
sde
sde
sde
sde
注意
这效果很好,但是为了简单地删除分号,
我再次使用cut
,这会添加另一个套接字作为|
。
期望
这可以通过awk本身进行调整,以便在一次调用中完成。
- 塞卡里欧2
原始数据:
Mar 20 05:15:02 transpire kernel: [15432418.855144] EXT4-fs (dm-13): error count since last fsck: 100
Mar 20 06:16:12 transpire kernel: [15436088.797185] EXT4-fs (dm-12): error count since last fsck: 20
Mar 20 07:17:22 transpire kernel: [15439758.736285] EXT4-fs (dm-15): error count since last fsck: 40
Mar 20 07:17:22 transpire kernel: [15439758.736293] EXT4-fs (dm-14): error count since last fsck: 2
Mar 20 19:48:50 transpire kernel: [15484846.579068] EXT4-fs (dm-11): error count since last fsck: 55
Mar 20 19:48:50 transpire kernel: [15484846.580064] EXT4-fs (dm-10): error count since last fsck: 41
Mar 21 05:16:49 transpire kernel: [15518924.611572] EXT4-fs (dm-13): error count since last fsck: 100
Mar 21 06:17:59 transpire kernel: [15522594.553205] EXT4-fs (dm-12): error count since last fsck: 20
Mar 21 07:19:09 transpire kernel: [15526264.495077] EXT4-fs (dm-14): error count since last fsck: 2
Mar 21 07:19:09 transpire kernel: [15526264.495086] EXT4-fs (dm-15): error count since last fsck: 4
0
# awk '/dm/{print $8|"sort -u"}' /var/log/messages
(dm-10):
(dm-11):
(dm-12):
(dm-13):
(dm-14):
(dm-15):
error
enter code here
试验:
# awk '/dm/{print $8|"sort -u"}' /var/log/messages|tr -d '():'|sed '$ d'
dm-10
dm-11
dm-12
dm-13
dm-14
dm-15
同样,如上所述,我无法弄清楚将其纳入单个 awk 调用,因此我正在使用tr
来切圆圈并sed
删除error
,因为这是最后一行。
期望:这可以在同一个尴尬的电话中完成吗?
使用您显示的示例,请尝试以下awk
解决方案:
要获得sde
的第一个输出,请尝试以下awk
代码。
awk -F',|[[:space:]]+' '/blk_update_request/ && $(NF-1)=="sector" {print $(NF-3)}' Input_file
要使第二个输出获得dm
值,请尝试以下awk
代码。
awk -F"[)(]" '!arr[$2]++{print $2 | "sort -n"}' Input_file
如果您使用dmesg | awk
作为第一个示例,/var/log/messages
作为第二个示例的输入文件,我将使用问题中的示例数据并从示例file
对于第一部分,您可以将字段分隔符更改为可选的逗号和 1 个或多个空格。
然后与字段 nr 7 和打印字段 nr 6 进行比较。
awk -F',?[[:space:]]+' '/blk_update_request/ && $7 =="sector"{ print $6 }' file
如果可以有多个逗号,您还可以替换字段 nr 6 中的所有逗号,然后打印出来。
awk '/blk_update_request/ && $7 =="sector"{ gsub(/,+/, "", $6); print $6 }' file
输出
sde
sde
sde
sde
sde
对于第二部分,您可以使用 gsub 将字符替换为空字符串,然后打印字段 nr 8。
awk '{ gsub(/[():]+/, "", $8); print $8 }' file | sort -u
输出
dm-10
dm-11
dm-12
dm-13
dm-14
dm-15
我会使用 GNUAWK
执行第二个任务,让file.txt
内容
Mar 20 05:15:02 transpire kernel: [15432418.855144] EXT4-fs (dm-13): error count since last fsck: 100
Mar 20 06:16:12 transpire kernel: [15436088.797185] EXT4-fs (dm-12): error count since last fsck: 20
Mar 20 07:17:22 transpire kernel: [15439758.736285] EXT4-fs (dm-15): error count since last fsck: 40
Mar 20 07:17:22 transpire kernel: [15439758.736293] EXT4-fs (dm-14): error count since last fsck: 2
Mar 20 19:48:50 transpire kernel: [15484846.579068] EXT4-fs (dm-11): error count since last fsck: 55
Mar 20 19:48:50 transpire kernel: [15484846.580064] EXT4-fs (dm-10): error count since last fsck: 41
Mar 21 05:16:49 transpire kernel: [15518924.611572] EXT4-fs (dm-13): error count since last fsck: 100
Mar 21 06:17:59 transpire kernel: [15522594.553205] EXT4-fs (dm-12): error count since last fsck: 20
Mar 21 07:19:09 transpire kernel: [15526264.495077] EXT4-fs (dm-14): error count since last fsck: 2
Mar 21 07:19:09 transpire kernel: [15526264.495086] EXT4-fs (dm-15): error count since last fsck: 4
然后
awk 'BEGIN{PROCINFO["sorted_in"]="@ind_str_asc";FPAT="dm-[[:digit:]]+"}NF{arr[$1]}END{for(i in arr){print i}}' file.txt
输出
dm-10
dm-11
dm-12
dm-13
dm-14
dm-15
说明:我通知 GNUAWK
使用索引作为字符串升序数组遍历,并且该字段dm-
后跟 1 位或多位数字。NF
是表示字段数的内置变量,当用作条件时,如果行中至少存在 1 个字段,则为 true。在这种情况下,我确实指的是键是数组arr
的字段。这确实在该数组中创建这样的键,请注意不必给出值。处理完所有行后,我使用for
print
所有键...in
按PROCINFO["sorted_in"]
规定的顺序.
(在Gawk 4.2.1中测试)
场景 1:
$ awk -F'[ ,]+' '/blk_update_request/ && ($7=="sector"){print $6}' file
sde
sde
sde
sde
sde
场景 2:
如果您只需要唯一值,则:
$ awk -F'[()]' '!seen[$2]++{print $2}' file
dm-13
dm-12
dm-15
dm-14
dm-11
dm-10
但是,如果您希望对它们进行排序,那么最有效(以及便携和强大)的方法是:
$ awk -F'[()]' '{print $2}' file | sort -t'-' -u -k1,1 -k2,2n
dm-10
dm-11
dm-12
dm-13
dm-14
dm-15
请注意,以上内容在数字部分按数字排序,因此如果您有dm
和/或单个或三位数或三位数以外的字符串以及两位数,它将全部正确排序(大概)。
您可以将调用移动到 awk 脚本内部的sort
,但您仍然有一个管道,并且会添加 awk 生成一个子外壳,这样效率会降低。