2

I opened up a document in vim and I want to search the document for IP addresses. So I used this command

/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}

But this pattern doesn't seem to return any of the IP addresses in my document. I can see there are IP addresses like 192.168.0.23 in my document.

What did I do wrong?

7

Vee has already given you the answer. I'd like to point out an equivalent but easier to type search pattern.

\v(\d{1,3}\.){3}\d{1,3}

\v enables very-magic mode, which allows no escaping on {() characters, and \d is a digit.

6

When trying to specify the number of matches to be 1 to 3 entries of the preceding sequence of numbers, the correct format is \{m,n}.

The manual reference is here.

Your example works when I change it to:

/[0-9]\{1,3}\.[0-9]\{1,3}\.[0-9]\{1,3}\.[0-9]\{1,3}

in my local test file. However, the correct 0-255 ip address regex is

/\s\zs\(\(25[0-5]\|2[0-4]\d\|[01]\?\d\?\d\)\.\)\{3\}\(25[0-5]\|2[0-4]\d\|[01]\?\d\?\d\_s\)

which is explained in the updates.

Edit

As pointed out in the comments, the . should be escaped to be \. to match it explicitly, otherwise you are able to get other non-ip address matches.

Shorter Search

Inspired by @quasímodo's answer, you can reduce this search a bit to

/\d\{1,3}\.\d\{1,3}\.\d\{1,3}\.\d\{1,3}

while his answer is definitely the shortest.

Another Update

@ChristianBrabandt made another good point that the above searches will match ip addresses that are not in the correct address range of 0-255.

His answer is shown below, but in an effort to reduce the expression, we get rid of most of the \_'s because they match the end-of-line where we will never see them, and replace a few [0-9]'s with \d's:

/\(\(25[0-5]\|2[0-4]\d\|[01]\?\d\?\d\)\.\)\{3\}\(25\_[0-5]\|2[0-4]\_[0-9]\|[01]\?\d\?\_[0-9]\)

Which yields the following search results: ChristianBrabandt_screenshot_result

Alas, it looks like some of the entries are still slightly improperly highlighted.

If we specify a space at the start of the match and start the match after that with

/\s\zs\(\(25[0-5]\|2[0-4]\d\|[01]\?\d\?\d\)\.\)\{3\}\(25\_[0-5]\|2[0-4]\_[0-9]\|[01]\?\d\?\_[0-9]\)

That fixes the bad ip address match of highlighting of 356.3.3.3, but what about the bad 255.255.255.256? I misused the \_ and applied it to the ending \_d/\_[0-9]. It works when adding it to a \_s at the end of the expression because we want to match either the end of line or a white space:

/\s\zs\(\(25[0-5]\|2[0-4]\d\|[01]\?\d\?\d\)\.\)\{3\}\(25[0-5]\|2[0-4]\d\|[01]\?\d\?\d\_s\)

It correctly omits 255.255.255.256: enter image description here

4
  • 1
    The . here is also matching "any character", so this will also match 192a168b0c23 and a range of other stuff that's not really an IP address... That's easily fixable by using \. for a literal dot instead.
    – filbranden
    Dec 3 '20 at 18:27
  • 1
    Good call @filbranden. I didn't think to check non-ip address cases. I'll make the edit.
    – Vee
    Dec 3 '20 at 18:29
  • 2
    Note, this also matches something like 1.999.256.500, which looks like an IPv4 but technically isn't. I have something like this in my VIMRC, (which I don't actually use, but just wanted to remember the pattern): match ipaddr /\(\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\.\)\{3\}\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)/ which is a bit more complex Dec 4 '20 at 7:27
  • Another good call @ChristianBrabandt, I'll add it to the answer.
    – Vee
    Dec 4 '20 at 15:22

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.