Little Code
Little Code

Reputation: 1545

Dot delimited parsing with awk

I have an output from a command that looks like the following:

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

The desired awk output is as follows:

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

My thinking at the moment is a bit messy (I'm no awk guru !), so my effort so far looks like this:

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

I guess I could continue with more pipes, but that is most likely the wrong method !

Upvotes: 1

Views: 3982

Answers (4)

Ed Morton
Ed Morton

Reputation: 204311

Assuming that testing for temp0 really is necessary and that your input can contain multiple types of report:

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

Upvotes: 2

Akshay Hegde
Akshay Hegde

Reputation: 16997

By using . and = as field separator using awk, use column 3,4,5

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

Better Readable version

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

Explanation

  • -F'[.=]' set field separator
hw.sensors.cpu0.temp0=39.00 degC
^    ^       ^    ^    ^  ^
col1 col2   col3 col4 col5 col6
  • -v fmt='hw_sensors{sensor="%s" reading="%s"} %d\n' variable fmt contains format string, similar to c/c++,
  • /temp0/{ search for line/row/records contains temp0
  • printf(fmt,$3,$4,$5) print your fields finally

Upvotes: 3

kvantour
kvantour

Reputation: 26531

This might be the easiest for you and most adaptable:

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]}'

This works in the following way:

  1. split each line in a key and value pair:

    line: hw.sensors.cpu0.temp0=39.00 degC
    => key=hw.sensors.cpu0.temp0
    => value=39.00 degC
    
  2. split the key in subparts based on the dot as delitimer, store the parts in array k:

    key=hw.sensors.cpu0.temp0
    split(key,k,/[.]/)
    => k=(hw,sensor,cpu0,temp0)
    
  3. split the value in subparts based on a blank as delimiter, sotre the parts in array v:

    value=39.00 degC
    split(value,v)
    => k=(39.00,degC)
    
  4. Reassemble the parts the way you like:

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

This method is very flexible, as you can now put conditions on the parts to determine the reassembling rule: example:

(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" }

Upvotes: 3

RavinderSingh13
RavinderSingh13

Reputation: 133710

Could you please try following.

awk -F'[.=]' -v s1="\"" '{print $1"_"$2"{"$2"="s1 $3 s1 " reading="s1 $4 s1 "} " $5+0}' Input_file

Upvotes: 2

Related Questions