0

On occasion I get output from a command that includes "key value" pairs, with possibly more than one pair per line. As a repeatable example, consider the command ip addr show dev eth0:

ip addr show dev eth0 | grep -v link/ether
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe0f:dbb3/64 scope link
       valid_lft forever preferred_lft forever

For the purposes of this example I might want to capture the values following mtu, inet, and brd (i.e. 1500, 10.0.2.15/24, and 10.0.2.255 respectively, here). It can be assumed that each keyword will not occur more than once in the input.

The only way I can see to handle this would be capture the output of the source command to a temporary variable, and repeatedly parse that until all the keywords have been processed.

Is there an easier or better way to pick out these "key value" pairs, discarding the remainder of the text?

Suggested example provision and unordered output:

ip addr show dev eth0 | someCommand brd inet mtu
mtu 1500
inet 10.0.2.15/24
brd 10.0.2.255
2
  • 1
    Just pipe the output to ... | tr \ \\n | sed -E '/^(mtu|inet|brd)$/!d;N;s/\n/ /' ; this assumes your keys and values are separated by a single space and keys/values cannot contain spaces. Commented Jul 15, 2015 at 12:34
  • @don_crissti that's an interesting approach (I tend to use sed for simple search/replace and avoid its loop and buffer options). Your example has given me opportunity to try out N too. Thank you! Commented Jul 15, 2015 at 13:52

2 Answers 2

1

Assuming that key name will appear at most once, here is how you may try.

ip addr show dev eth0 | perl -ne 'chomp; foreach $param (qw(mtu inet brd)) { /($param)\s+(\S+)/ && do { print "$1 $2\n"; }}'
1

Here's an awk solution which puts each word on its own line, and whenever it finds one of the specified keys, prints it and the following word. The keys are in fact a regular expression that needs to match the whole word.

ip addr show dev eth1 |
tr -s ' ' '\n' |
awk -v keys='mtu|inet|brd' '
    match($0, "^(" keys ")$") {printf "%s ", $0; getline; print}
'

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.