【问题标题】:reading output of command or read from a file读取命令的输出或从文件中读取
【发布时间】:2012-07-20 12:16:43
【问题描述】:

我是 bash 新手,想改进。我需要学习从文件或命令输出中读取特定文本。例如,我想从 /proc/interrupts 文件中计算计算机每个内核的总以太网中断数。文件的内容是:

CPU0       CPU1       CPU2       CPU3
0:        142          0          0          0   IO-APIC-edge      timer
1:          1          0          1          0   IO-APIC-edge      i8042
4:        694         18        635         19   IO-APIC-edge      serial
7:          0          0          0          0   IO-APIC-edge      parport0
9:          0          0          0          0   IO-APIC-fasteoi   acpi
12:          1          1          0          2   IO-APIC-edge      i8042
14:          0          0          0          0   IO-APIC-edge      ide0
19:          0          0          0          0   IO-APIC-fasteoi   uhci_hcd:usb3
23:          0          0          0          0   IO-APIC-fasteoi   ehci_hcd:usb1,  uhci_hcd:usb2
46:     347470     119806     340499     108227   PCI-MSI-edge      ahci
47:      33568      45958      46028      49191   PCI-MSI-edge      eth0-rx-0
48:          0          0          0          0   PCI-MSI-edge      eth0-tx-0
49:          1          0          1          0   PCI-MSI-edge      eth0
50:      28217      42237      65203      39086   PCI-MSI-edge      eth1-rx-0
51:          0          0          0          0   PCI-MSI-edge      eth1-tx-0
52:          0          1          0          1   PCI-MSI-edge      eth1
59:     114991     338765      77952     134850   PCI-MSI-edge      eth4-rx-0
60:     429029     315813     710091      26714   PCI-MSI-edge      eth4-tx-0
61:          5          2          1          5   PCI-MSI-edge      eth4
62:    1647083     208840    1164288     933967   PCI-MSI-edge      eth5-rx-0
63:     673787    1542662     195326    1329903   PCI-MSI-edge      eth5-tx-0
64:          5          6          7          4   PCI-MSI-edge      eth5

我需要使用“eth”关键字读取所有中断数,然后找到每个 CPU 核心的总和(无论 CPU 核心名称是什么)。例如对于 CPU0:33568+0+1+28217... 什么适合这个?我必须将 awk 或 sed 用于正则表达式吗?

【问题讨论】:

    标签: regex linux bash shell


    【解决方案1】:

    您可以为此使用awk不需要 grep 或任何其他工具,因为 awk 可以自己进行搜索。

    更新

    基于不同数量的 CPU 列的可能性(请参阅下面的第一条评论),这将起作用:

    NR==1 {
      core_count = NF
      print "core count: ", core_count
      next
    }
    /eth/ {
      for (i = 2; i <= 2+core_count; i++)
        totals[i-2] += $i
    }
    
    END {
      print "Totals"
      for (i = 0; i < core_count; i++)
        printf("CPU%d: %d\n", i, totals[i])
    }
    

    给出输出:

    core count:  4
    Totals
    CPU0:  2926686
    CPU1:  2494284
    CPU2:  2258897
    CPU3:  2513721
    

    备注

    如果第一行仅包含 CPU 标头,则使用脚本开头所示的NF 将起作用。如果可能存在其他数据,则可以使用core_count = gsub(/CPU/, "CPU")。此外,此脚本依赖于连续的 CPU 列。

    【讨论】:

    • 这是一个很好的答案,但 CPU0 是静态的。如果我不知道 CPU 内核的名称和数量怎么办。例如,如果它以 cPU1 开头并经过 CPU9。我必须阅读内核名称之前并分配给这个脚本的变量,或者有没有办法在这个脚本中读取
    • @barp 试一试,最好使用不同数量的 CPU 列,让我知道这是否适合您。我在这里使用数组,仅供参考。另请注意,我正在打印脚本第 3 行中找到的内核数量,如果不需要,您可以将其删除(认为这可能有助于调试)。
    • 从报告的结构来看,我猜 NR 足以检测到 CPU 的数量。
    • @nshy 好点.. 我想我可以改变它并记下它,不需要其他数据。感谢您指出这种简化。
    • @Levon 如果您从 0 迭代到 core_count 并设置 totals[i] += $(i+2),循环也会简单得多
    【解决方案2】:

    您可以使用grep 过滤掉eth 行,然后使用sum using awk

    例如对于 CPU 1 和 2:

    grep eth report | awk '{ CPU0 += $2; CPU1 += $3} END { print CPU0; print CPU1} ' 
    

    请注意,您可以filter within awk,而不是为此使用grep

    不过,我可能很想在 Perl 中执行此操作,并为每个 CPU 创建一个总和哈希值。这将取决于我想要实现的可扩展性。

    【讨论】:

    • 这是一个很好的答案,但 CPU0 是静态的。如果我不知道 CPU 内核的名称和数量怎么办。例如,如果它以 cPU1 开头并经过 CPU9。我必须阅读内核名称之前并分配给这个脚本的变量,或者有没有办法在这个脚本中读取
    猜你喜欢
    • 2017-12-15
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多