使用 Awk 作为单行传递数据,避免使用管道打开多个套接字



我有一个关于用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的字段。这确实在该数组中创建这样的键,请注意不必给出值。处理完所有行后,我使用forprint所有键...inPROCINFO["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 生成一个子外壳,这样效率会降低。

最新更新