Search code examples
linuxawkcutgawk

How to make this awk command more simple


Is there a way to make this command more simple (ie. not using awk twice):

awk '/cpu MHz/ {print $4}' < /proc/cpuinfo | awk -F'.' 'NR==1 {print $1}'

?

Also, is there a way to avoid using cut command here:

ip addr show dev eth0 | awk '$1=="inet" {print $2}' | cut -f1 -d '/'

?

Thanks.


Solution

  • First one is like this:

    awk '/cpu MHz/ {print $4}' < /proc/cpuinfo | awk -F'.' 'NR==1 {print $1}'
    

    Considering you have a string like this:

    cpu MHz         : 800.000
    cpu MHz         : 800.000
    cpu MHz         : 800.000
    cpu MHz         : 800.000
    

    And you want the integer part of the number just for first line, you can do:

    $ awk -F"[ .]" '/cpu MHz/ {print $(NF-1); exit}' /proc/cpuinfo
    800
    

    That is, to match the line, print the penultimate field and then exit to avoid extra processing.

    As per comments, you also want to get the 2nd matching line in a different command. For this, you can do:

    awk -F"[ .]" '/cpu MHz/ {if (f) {print $(NF-1); exit}; f=1}' /proc/cpuinfo
    

    What it does is to use a flag. On the first match, the flag is activated, so on next one it prints the value and exits.


    Second one is like this:

    ip addr show dev eth0 | awk '$1=="inet" {print $2}' | cut -f1 -d '/'
    

    What you can do is to split the second field in slices based on / and print the first one:

    $ ip addr show dev eth0 | awk '$1=="inet" {split($2, a, "/"); print a[1]}'
    192.168.123.123