0

I've got a bash variable containing several lines of text, which includes IP addresses, and I need to remove 'everything' before the last IP address occurrence in the same line.

This:

43.12.40.53 [email protected] archery-666.foobar.com 66.77.11.44 data test@example 55.32.39.153 [email protected] 5.113.30.37 dummy 89-109-22-006.static.example.com.br 89.109.22.6 [email protected] 68.28.15.55 68.28.15.55 another 

should be transform into:

43.12.40.53 [email protected] 66.77.11.44 data test@example 55.32.39.153 [email protected] 5.113.30.37 dummy 89.109.22.6 [email protected] 68.28.15.55 another 

Reading this post How can I delete everything until a pattern and everything after another pattern from a line? I tried:

var=$(sed 's/^.*\(([0-9]{1,3}[\.]){3}[0-9]{1,3}\).*$/\1/' <<< "$var") 

but it doesn't work.

2 Answers 2

2

A couple of issues:

  1. you're mixing BRE and ERE (for example \( versus ( for the grouping)

  2. your .* at the end needs to be inside the capture group if you want the result to include everything after the IP

  3. the ^.* at the beginning will greedily consume as many characters as it can - including all but one of the leading IP digits

Also, . doesn't need to be escaped inside [] - although that doesn't break anything.

I'm not sure the RIGHT way to deal with (3) in sed which (unlike perl say) doesn't have a non-greedy modifier. Adding a word-boundary anchor \b seems to work but feels fragile

So either (BRE)

sed 's/^.*\(\b\([0-9]\{1,3\}[.]\)\{3\}[0-9]\{1,3\}.*$\)/\1/' <<< "$var" 

or (ERE)

sed -E 's/^.*(\b([0-9]{1,3}[.]){3}[0-9]{1,3}.*$)/\1/' <<< "$var" 
1

You have correctly escaped the 1st parentheses, but not the second and not the {} which also need escaping. Also, you are matching everything to the end of the line (.*$) which isn't needed. Using your regex, this would do what you want:

$ sed 's/^.*\(\([0-9]\{1,3\}[\.]\)\{3\}[0-9]\{1,3\}\)/\1/' <<< "$var" 3.12.40.53 [email protected] 6.77.11.44 data test@example 5.32.39.153 [email protected] 5.113.30.37 dummy 9.109.22.6 [email protected] 8.28.15.55 another 

But this is still more complicated than necessary. For example, you don't need [\.], a simple \. is enough. And you can use the -E flag to enable extended regular expressions and simplify your syntax to:

$ sed -E 's/^.*(([0-9]{1,3}\.){3}[0-9]{1,3})/\1/' <<< "$var" 3.12.40.53 [email protected] 6.77.11.44 data test@example 5.32.39.153 [email protected] 5.113.30.37 dummy 9.109.22.6 [email protected] 8.28.15.55 another 

However, as steeldriver points out, your leading .* might eat up more than you expect, so it would be safer to do the whole thing in perl instead:

$ perl -pe 's/^.*?(([\d]{1,3}\.){3}\d{1,3})/\1/' <<< "$var" 43.12.40.53 [email protected] 66.77.11.44 data test@example 55.32.39.153 [email protected] 5.113.30.37 dummy 89.109.22.6 [email protected] 68.28.15.55 68.28.15.55 another 

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.