6

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“.)

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...).*$
  • 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 at 9: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 at 17:11
  • 2
    it works a bit like && in most coding language: is brilliant! – Maxim Kim May 15 at 8: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
  • nicely explained, therefore +1 – myrdd May 15 at 8:12
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)@!
                    ‾      ‾      ‾
  • 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 at 13:42
  • thank you @Rich for your edit and your suggestion! – myrdd May 18 at 3:36

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.