Разбор с разделителями точками с помощью awk - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть вывод команды, которая выглядит следующим образом:

hw.sensors.cpu0.temp0=39.00 degC
hw.sensors.acpitz0.temp0=27.80 degC (zone temperature)

Требуемый вывод awk выглядит следующим образом:

# TYPE hw_sensors gauge
hw_sensors{sensor="cpu0" reading="temp0"} 39
hw_sensors{sensor="acpitz0" reading="temp0"} 27

На данный момент я думаю следующее:немного грязно (я не awk гуру!), так что мои усилия пока выглядят так:

sysctl hw.sensors | fgrep temp0 | sed 's/\./_/g' | awk '{FS="="; print "# TYPE "$1" gauge\n"$1" "$2}' | sed -E 's/_[[:digit:]]{1,2}.*$//g' 

Я думаю, что я мог бы продолжить с большим количеством каналов, но это, скорее всего, неправильный метод!

Ответы [ 4 ]

2 голосов
/ 25 сентября 2019

Предполагая, что тестирование для temp0 действительно необходимо и что ваш ввод может содержать несколько типов отчетов:

sysctl hw.sensors |
awk -F'[.=]' '
    !/temp0/ { next }
    { type = $1 "_" $2 }
    !doneHdr[type]++ { printf "# TYPE %s gauge\n", type }
    { printf "%s{sensor=\"%s\" reading=\"%s\"} %d\n", type, $3, $4, $5 }
'
# TYPE hw_sensors gauge
hw_sensors{sensor="cpu0" reading="temp0"} 39
hw_sensors{sensor="acpitz0" reading="temp0"} 27
2 голосов
/ 25 сентября 2019

Не могли бы вы попробовать следующее.

awk -F'[.=]' -v s1="\"" '{print $1"_"$2"{"$2"="s1 $3 s1 " reading="s1 $4 s1 "} " $5+0}' Input_file
2 голосов
/ 25 сентября 2019

Используя . и = в качестве разделителя полей, используя awk, используйте столбец 3,4,5

sysctl hw.sensors | awk -F'[.=]' -v fmt='hw_sensors{sensor="%s" reading="%s"} %d\n' '/temp0/{ printf(fmt,$3,$4,$5) }'

Лучше читаемая версия

sysctl hw.sensors | \
awk -F'[.=]' -v fmt='hw_sensors{sensor="%s" reading="%s"} %d\n' '
/temp0/{ 
     printf(fmt,$3,$4,$5) 
}'

Пояснение

  • -F'[.=]' установить разделитель полей
hw.sensors.cpu0.temp0=39.00 degC
^    ^       ^    ^    ^  ^
col1 col2   col3 col4 col5 col6
  • -v fmt='hw_sensors{sensor="%s" reading="%s"} %d\n' переменная fmt содержит строку формата,аналогично c/c++,
  • /temp0/{ поиск строки / строки / записи содержит temp0
  • printf(fmt,$3,$4,$5) напечатать ваши поля окончательно
2 голосов
/ 25 сентября 2019

Это может быть самым простым для вас и наиболее адаптируемым:

awk 'BEGIN{FS="="}'
     {key=$1; value=$2}
     {split(key,k,/[.]/)}
     {split(value,v)}
     {print k[1]"_"k[2]"{sensor=\042" k[3] "\042 reading=\042"k[4]"\042}",v[1]}'

Это работает следующим образом:

  1. разбить каждую строку на ключ и значениепара:

    line: hw.sensors.cpu0.temp0=39.00 degC
    => key=hw.sensors.cpu0.temp0
    => value=39.00 degC
    
  2. разделить ключ на части на основе точки в качестве делитера, сохранить детали в массиве k:

    key=hw.sensors.cpu0.temp0
    split(key,k,/[.]/)
    => k=(hw,sensor,cpu0,temp0)
    
  3. разделить значение в подчастях на основе пробела в качестве разделителя, sotre части в массиве v:

    value=39.00 degC
    split(value,v)
    => k=(39.00,degC)
    
  4. Собрать части так, как вам нравится:

    print k[1]"_"k[2]"{sensor=\042" k[3] "\042 reading=\042"k[4]"\042}",v[1]
    

Этот метод очень гибкий, так как теперь вы можете наложить на детали условия для определения правила повторной сборки: пример:

(k[2]=="sensor"){ print k[1]"_"k[2]"{sensor=\042" k[3] "\042 reading=\042"k[4]"\042}",v[1] }
(k[2]=="dog") { print "This dog is",v[1], "cm long" }
...