使用SED将传感器命令输出转换为可记录条目

时间:2016-11-25 17:55:28

标签: linux sed

考虑以下sensor命令输出:

amdgpu-pci-0100
temp1:        +67.0°C  crit =  +0.0°C, hyst =  +0.0°C

amdgpu-pci-0600
temp1:        +59.0°C  crit =  +0.0°C, hyst =  +0.0°C

amdgpu-pci-0700
temp1:        +64.0°C  crit =  +0.0°C, hyst =  +0.0°C

it8721-isa-0290
Vbat:         +3.43 V
temp1:        +43.0°C  low  = +97.0°C, high = -90.0°C  ALARM  sensor = thermistor
temp2:        +40.0°C  low  = +79.0°C, high =  +2.0°C  ALARM  sensor = thermistor
temp3:       -128.0°C  low  = -128.0°C, high = +69.0°C  sensor = disabled

k10temp-pci-00c3
temp1:        +25.1°C  high = +70.0°C
                       crit = +90.0°C, hyst = +87.0°C

fam15h_power-pci-00c4
power1:       13.04 W  crit =  94.99 W

asus-isa-0000
cpu_fan:        0 RPM

我正在尝试将其转换为日志条目,就像这样,“temp1”值放在PCI适配器和电路板旁边(it8721-isa-0290):

<Date_Time> amdgpu-pci-0100  -  +67.0°C  |  amdgpu-pci-0600  -  +59.0°C  |  amdgpu-pci-0700  -  +64.0°C  |  it8721-isa-0290  -  +43.0°C

我认为sed是正确的工具,但如果不是,请告诉我。我已经使用2个sed命令修剪了一些数据,但是我不太确定如何删除我不需要的其余部分或仅仅根据我需要的东西进行匹配。非常感谢一些帮助。

编辑:以下是我迄今为止的命令:

sensors | sed -e '/Adapter/d' -e '/in/d' -e 's/[)(]//g' -e '/Vbat/d' \
`-e 's/crit.*//' -e 's/low.*//' -e '/temp2/d' -e '/temp3/d' -e '/^k10temp-pci-`00c3$/,$d' \
-e 's/temp.://'

这是输出(只需要添加一些分隔符):

amdgpu-pci-0100 +68.0°C amdgpu-pci-0600 +60.0°C amdgpu-pci-0700 +65.0°C it8721-isa-0290 +44.0°C

有没有更简单的方法来完成我的工作?

5 个答案:

答案 0 :(得分:0)

我确信有更优雅的方法可以做到这一点,但也许它可能有所帮助:

sensors | egrep -o "\S+-\S+|\+[0-9]+\...C" | egrep "\S+-\S+" -A 1 | sed 's/--/|/g' | head -n -3 | tr '\n' ' '

如果第一个grep仅匹配字符串此类和温度值,则第二个grep再次匹配字符串类似此字符和每个字符串之后的一行,sed转换 - (由第二个grep生成)到| ,然后head删除最后3个字符串(这仅适用于您的特定输出),tr删除换行符。

答案 1 :(得分:0)

你说:“最后一个是非常难编码的,我不喜欢它,因为它不是很灵活。”这是事实,但我认为这个问题是产生数据的过程所固有的,而不是用于生成所需输出的工具。 我想出了这个解决方案。如果您对我使用的命令的详细信息感兴趣,请询问:

 sensors | sed -n -e '/^k10temp-pci-00c3$/,$ s/.*//; /^[^ \\\t]\+$/ H;' \
       -e '/^temp1:/ {s/^temp1:[ \\\t]\+\([+-][0-9]*.[0-9]\+°C\).*/\1/; H;}' \
       -e '$ {x; s/^\n//; :start /\n/ {s/\n/ - /; s/\n/ | /; b start;}; s/^\(.*\)/<Date Time> \1/; p;}'

答案 2 :(得分:0)

目前还不清楚你要做什么,但这会从你发布的输入中产生你想要的输出:

$ cat tst.awk
/^[^[:space:]:]+$/ { name = $0 }
name == "k10temp-pci-00c3" { print ts, rec; exit }
$1 == "temp1:" { rec = (rec=="" ? "" : rec "  |  ") name "  -  " $2 }

$ awk -v ts="$(date +'%F %T')" -f tst.awk file
2016-11-26 09:26:35 amdgpu-pci-0100  -  +67.0°C  |  amdgpu-pci-0600  -  +59.0°C  |  amdgpu-pci-0700  -  +64.0°C  |  it8721-isa-0290  -  +43.0°C

这就是你要做的 - 在k10之前打印每个bock的第一个temp1值吗?

答案 3 :(得分:0)

sensors命令的输出很大程度上取决于配置文件。例如,rename the labels可以使用类似于以下内容的配置:

chip "as99127f-*"
  label temp1 "Mobo Temp"
  label temp2 "CPU0 Temp"

使用这样的配置,sensors命令的输出将如下所示:

Mobo Temp:        +35.0°C  (high =  +0.0°C, hyst = -128.0°C)
CPU0 Temp:        +47.5°C  (high = +100.0°C, hyst = +75.0°C)

但是,sensors实用程序提供了-u开关,用于打印易于解析的原始数据。在原始模式下,芯片功能名称以标准格式打印,例如temp1_inputtemp1_maxtemp1_crittemp1_crit_alarm,例如:

acpitz-virtual-0
Adapter: Virtual device
temp1:
  temp1_input: 64.000
  temp1_crit: 120.000
temp2:
  temp2_input: 30.000
  temp2_crit: 120.000

coretemp-isa-0000
Adapter: ISA adapter
Physical id 0:
  temp1_input: 67.000
  temp1_max: 87.000
  temp1_crit: 105.000
  temp1_crit_alarm: 0.000
Core 0:
  temp2_input: 67.000
  temp2_max: 87.000
  temp2_crit: 105.000
  temp2_crit_alarm: 0.000
  ...

格式仍然不像解析那样容易(想想JSON或XML)。芯片功能块用换行符分隔。每个块都以芯片名称开头。所以你需要记住块何时开始,并在块结束时打印(空行或文件结尾)。

可以在AWK中实现该算法。甚至可以在SED中执行此操作。但我觉得这些工具对这种情况不方便。我宁愿使用更灵活的工具,比如Perl(也许我刚刚使用Perl而不是AWK)。

示例

sensors-temp.pl

#!/usr/bin/perl
my $nl = 0;
my $chip;
my @t;

while (<>) {
  if ($chip eq "" or $nl) {
    ($chip = $_) =~ s/\n*$//;
    @t = ()
  } elsif ($_ =~ /temp\d+_input: ([\d\.]+)/m) {
     push @t, $1;
  }

  $nl = $_ eq "\n";

  # Average chip's temperature
  if ($nl or eof()) {
    my $t; map { $t += $_ } @t;
    printf("%s - %.1f°C\n", $chip, $t / (scalar @t))
  }
}

用法

sensors -u | perl sensors-temp.pl

示例输出

acpitz-virtual-0 - 47.5°C
coretemp-isa-0000 - 65.4°C

该脚本计算temp\d+_input条目的平均温度。您可以轻松更改脚本以满足我们的需求。例如,为了打印所有&#34;输入&#34;的列表。芯片的温度,用以下内容替换回路中的最后一个块:

printf("%s - %s°C\n", $chip, join("|", map { sprintf("%.1f", $_) } @t))
  if $nl or eof();

示例输出

acpitz-virtual-0 - 67.0|30.0°C
coretemp-isa-0000 - 68.0|67.0|63.0|66.0|61.0°C

<强> P.S。

为清晰起见,示例中的代码为每个芯片打印换行符。将换行符(\n)替换为&#34; | &#34;,或任何你认为适合你的情况。

答案 4 :(得分:-1)

sensors | sed -e '/Adapter/d' -e '/in/d' -e 's/[)(]//g' -e '/Vbat/d' \
`-e 's/crit.*//' -e 's/low.*//' -e '/temp2/d' -e '/temp3/d' -e '/^k10temp-pci-`00c3$/,$d' \
-e 's/temp.://'

sensors - 获取原始输出

'/Adapter/d' - 删除包含“Adapter”的行

'/in/d' - 删除包含“in”

的行

's/[)(]//g' - 删除括号

'/Vbat/d' - 删除包含“Vbat”的行

's/crit.*//' - 删除行上“暴击”后的所有内容

's/low.*//' - 删除行上“低”后的所有内容

'/temp2/d' - 删除包含“temp2”的行

'/temp3/d' - 删除包含“temp3”的行

'/^k10temp-pci-00c3$/,$d' - 删除“k10temp-pci-`00c3”后的所有内容

最后一个是非常硬编码的,我不喜欢它,因为它不是很灵活。