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

3 Answers 3

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.