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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.