8

ip a produces bunch IP Addresses and interfaces status

With awk '/inet / {print $2}', I manage to get the IP and the subnet

wolf@linux:~$ ip a | awk '/inet / {print $2}'
127.0.0.1/8
10.10.0.1/24
10.10.1.1/24
wolf@linux:~$ 

Then, I pipe it to another awk to remove the CIDR notation.

wolf@linux:~$ ip a | awk '/inet / {print $2}' | awk -F / '{print $1}'
127.0.0.1
10.10.0.1
10.10.1.1
wolf@linux:~$ 

Is it possible to do this without piping the awk output to another awk?

Desired Output

wolf@linux:~$ ip a | <awk syntax here without additional piping>
127.0.0.1
10.10.0.1
10.10.1.1
wolf@linux:~$ 
1
  • 5
    Non-awk solution is of course to pipe to cut -f 1 -d / which could be more easily understood by the next reader of your code.
    – Pål GD
    May 23, 2020 at 11:30

4 Answers 4

12

Actually the field separator you define usung -F is a regular expression. Thus the following command should deliver:

ip a | awk -F'[ /]+' '/inet / {print $3}'
0
11
ip a | awk '/inet / {FS="/"; $0=$2; print $1; FS=" "}'

The first matching record is split into fields according to the default FS (space). Then a new FS is set. When we substitute $0=$2, splitting is done again according to the new FS. Now $1 contains what we want, we print it. Finally we set FS for the next matching record.

2
  • Thanks. Both solution works. Which one should I accept?
    – Wolf
    May 23, 2020 at 2:22
  • 1
    @Wolf accept the one you personally feel is best for your need, or you find easiest to understand. And upvote all answers that are helpful.
    – Criggie
    May 24, 2020 at 3:18
10

For this very specific case, have you considered a better use of ip? For example:

ip -j -p -f inet a | awk -F \" '/local/ {print $4}'

This will print ip address as a JSON object an search for the local key, which happens to store the IP address. Is is even sharper you can use jq:

ip -j -p -f inet a | jq '.[].addr_info[].local'

I recommend this last command as it will not suffer from changes in ip addr output. However, if you really like your initial design, I would go with:

ip a | awk '/inet / {print substr($2, 1, index($2,"/")-1)}'

or

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

In the first command, we use index($2, "/") to find where / is in $2 and then use substr to generate the substring. In the seconds one, we split $2 on / and store it on addr array.

0
7

You could replace the / and the following characters with an empty string:

ip a | awk '/inet /{ sub(/\/.*/, "", $2); print $2 }'
2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .