7

Suppose we have the following very simple file:

1 x 3 x
x 3 x 1

Now I'd like to have a pattern that matches all lines containing both 1 and 3. The order and position should not matter.

(Note that I used a very simple file on purpose. The file could contain many more lines, and the ”words“ could be words like ”hello“ and ”world“.)

myrdd
  • 203
  • 1
  • 2
  • 7

3 Answers3

7

Another way is to use :h /\& , it works a bit like && in most coding language:

pattern0\&pattern1

Above expression will match pattern1 if pattern0 also match at the same position.

To solve your example:

\v^(.*1&.*3).*$
  • \v very magic
  • ^ start of line
  • (.*1&.*3) match .*3 if .*1 matches.
  • .*$ match anything until line end

If you have multiple patterns, you can write it as:

\v^(.*pattern0&.*pattern1&.*pattern2...).*$
dedowsdi
  • 6,248
  • 1
  • 18
  • 31
  • 2
    I've never really understood what /\& is for. Now I do. Which is weird, because this is essentially identical to the "Peter and Bob" example given in the :help. Still, reading your answer, it finally clicked in my brain. Thanks! +1 – Rich May 14 '19 at 09:52
  • 3
    This is way easier to type in general, and I (like Rich) learned something. +1; this should be the accepted answer. – D. Ben Knoble May 14 '19 at 17:11
  • 2
    it works a bit like && in most coding language: is brilliant! – Maxim Kim May 15 '19 at 08:20
4

Here's another alternative: use :h /bar to match either …1…3… or …3…1…:

\v.*(1.*3|3.*1).*
  • \v very magic
  • .* anything (or nothing)
  • (...) a group, containing either:
    • 1.*3 1 followed by anything followed by 3
    • | or
    • 3.*1 3 followed by anything followed by 1
  • .* anything
Rich
  • 31,891
  • 3
  • 72
  • 139
3

One option is to use a pattern with multiple lookaheads:

magic:        ^\(.*1\)\@=\(.*3\)\@=
                   ‾         ‾

very magic:   \v^(.*1)@=(.*3)@=
                    ‾      ‾

Since lookaheads (and lookarounds in general) do not consume characters, the same line can be searched for multiple different patterns/words.


additional hint:

This even allows one to add another condition to the regular expression: matching lines that contain 1 and 3, but do not contain x:

magic:        ^\(.*1\)\@=\(.*3\)\@=\(.*x\)\@!
                   ‾         ‾         ‾

very magic:   \v^(.*1)@=(.*3)@=(.*x)@!
                    ‾      ‾      ‾
myrdd
  • 203
  • 1
  • 2
  • 7
  • 1
    I'd consider removing the \<, \>, <, and > end-of-word atoms from this answer. They're not required for the simple example given in your question, and your regular expressions are easier to understand without them! – Rich May 16 '19 at 13:42
  • thank you @Rich for your edit and your suggestion! – myrdd May 18 '19 at 03:36