sed return multiple next-word results on one string

Viewed 263

Is it possible to return multiple next word results using a single sed query

String:

profile string.www.com { app-service none cert string.www.com_2018_2020.crt cert-key-chain { string.www.com _2018_2020_geotrust_rsa_ca_2018 { cert string.www.com _2018_2020.crt chain geotrust_rsa_ca_2018.crt key string.www.com_2018_2020.key } } chain geotrust_rsa_ca_2018.crt defaults-from default-clientssl inherit-certkeychain false key string.www.com_2018_2020.key passphrase none }

So for instance something like:

sed -n 's/^.*\(profile \|defaults-from \| passphrase) \([^ ]*\).*/\1/p'

Would return:

string.www.com
default-clientssl
none
2 Answers

This might work for you (GNU sed):

sed -En '/\n/!s/(profile|defaults-from|passphrase) \S+/\n&\n/g;/^(profile|defaults-from|passphrase)/P;D' file

Surround the required keys and values by newlines and only print those keys and values when they present themselves at the start of the line.

To output only the value:

sed -En '/\n/!s/(profile|defaults-from|passphrase) \S+/\n&\n/g;/^(profile|defaults-from|passphrase)/{s/\S+ //;P};D' file

You can't easily extract multiple matches on the same line with sed as its patterns are always "greedy". You may do it with two steps:

sed 's/\(profile\|defaults-from\|passphrase\) \([^ ]*\)/\nXXX\2XXX\n/g' <<< "$s" | \
 sed -n 's/^XXX\(.*\)XXX$/\1/p'

First, wrap the matches with XXX and newlines, and then grab those matches with sed -n 's/^XXX\(.*\)XXX$/\1/p'. See this online demo.

If you want a "sngle-step" solution, you can extract those texts much easier with grep.

GNU grep solution:

grep -oP '(profile|defaults-from|passphrase)\s+\K\S+' file

Or, with pcregrep:

pcregrep -o '(profile|defaults-from|passphrase)\s+\K\S+' file

See this online demo.

Related