How can I find where one word is close to another word?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How can I find where one word is close to another word?

Adrian Keister

As most people on this forum are likely aware, searching for a word is straight-forward enough. If I want to find occurrences of the word 'arc', I can type / arc , with spaces around the three letters, to find basic occurrences of the word (ignoring punctuation). But suppose I want to find where two words are close together, say, within ten words? Here's an example:

Now is the time for all good men to come to the aid of their country.

In this test, I want to find all occurrences where the word 'aid' is within ten words of the word 'country'. How can I do that in Vim?


This is cross-posted on Vi and Vim Beta.


Thanks!

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/b8c05daf-96a6-4840-929e-388f64e2ea37o%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: How can I find where one word is close to another word?

Tim Chase
On 2020-07-25 15:59, Adrian Keister wrote:
> Now is the time for all good men to come to the aid of their
> country.
>
> In this test, I want to find all occurrences where the word 'aid'
> is within ten words of the word 'country'. How can I do that in Vim?

It's way ugly and requires using the old regex engine[1] (asserted by
the "\%#=1" in the following pattern) to work, but this should do the
trick and be fairly DRY (only requires putting in each term once):

  \%#=1\%(\S\+\_s\+\)\{,9}\<aid\>\&\%(\S\+\_s\+\)\{,9}\<country\>

I might have a fenceposting issue where "9" should be "8" or "10",
but it should give you the foundation to mess around.  Also, I added
the "\<" and "\>" to anchor the words so you don't find things like
"I said my uncle is a country boy" (finding the "aid" in "said").
Again, season to taste for your own needs.

The cursor lands a little weirdly (especially noticable if you have
syntax highlighting turned on) because it starts from the point at
which "within the next N words you'll find "aid" and within the next N
words you'll also find "country".

Alternatively, if you don't mind typing your literals more than once,
you can do

  /\<aid\>\%(\_s\+\S\+\)\{,10}\_s\+\<country\>\|\<country\>\%(\_s\+\S\+\)\{,10}\_s\+\<aid\>

which will highlight a little more neatly at the cost of extra typing.
However, it also doesn't scale as well if you have more than 2 words
because you need to provide every possible ordering.  The method at
the top scales easily for however many words you want within an
N-word range.

Hopefully one or the other works well for you.  

-tim


[1] For the record, the new regex engine gives me an

  E363: pattern uses more memory than 'maxmempattern'

where the old engine works fine.




--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/20200725184223.312a64f2%40bigbox.attlocal.net.
Reply | Threaded
Open this post in threaded view
|

Re: How can I find where one word is close to another word?

Adrian Keister
Tim,

Many thanks!

There's an answer on the Stack Exchange site. Does that method work also?

Cheers.

On Saturday, July 25, 2020 at 6:42:37 PM UTC-5, Tim Chase wrote:
On 2020-07-25 15:59, Adrian Keister wrote:
> Now is the time for all good men to come to the aid of their
> country.
>
> In this test, I want to find all occurrences where the word 'aid'
> is within ten words of the word 'country'. How can I do that in Vim?

It's way ugly and requires using the old regex engine[1] (asserted by
the "\%#=1" in the following pattern) to work, but this should do the
trick and be fairly DRY (only requires putting in each term once):

  \%#=1\%(\S\+\_s\+\)\{,9}\<aid\>\&\%(\S\+\_s\+\)\{,9}\<country\>

I might have a fenceposting issue where "9" should be "8" or "10",
but it should give you the foundation to mess around.  Also, I added
the "\<" and "\>" to anchor the words so you don't find things like
"I said my uncle is a country boy" (finding the "aid" in "said").
Again, season to taste for your own needs.

The cursor lands a little weirdly (especially noticable if you have
syntax highlighting turned on) because it starts from the point at
which "within the next N words you'll find "aid" and within the next N
words you'll also find "country".

Alternatively, if you don't mind typing your literals more than once,
you can do

  /\<aid\>\%(\_s\+\S\+\)\{,10}\_s\+\<country\>\|\<country\>\%(\_s\+\S\+\)\{,10}\_s\+\<aid\>

which will highlight a little more neatly at the cost of extra typing.
However, it also doesn't scale as well if you have more than 2 words
because you need to provide every possible ordering.  The method at
the top scales easily for however many words you want within an
N-word range.

Hopefully one or the other works well for you.  

-tim


[1] For the record, the new regex engine gives me an

  E363: pattern uses more memory than 'maxmempattern'

where the old engine works fine.




--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/48d56df2-d7dc-4a57-9412-158bc1e629fbo%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: How can I find where one word is close to another word?

Tim Chase
On 2020-07-25 17:54, Adrian Keister wrote:
> There's an answer on the Stack Exchange site. Does that method work
> also?

That method finds only the case in which you have "aid" *followed by*
"country", so if you have

  "This country needs all good men to come to her aid."

it won't find that even though "country" and "aid" are within 10
words of each other.

You might recognize that it's pretty similar to the first half of my
2nd answer:  "term1(N optional words)term2" which I then swap around
with "or term2(N optional words)term1".

So if you only need "X with Y following it within N words", that's
an easy solution.  If you need to allow for arbitrary ordering of the
words, you need a bit more such as either of my suggestions.

-tim



--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/20200725204142.7d61ace4%40bigbox.attlocal.net.
Reply | Threaded
Open this post in threaded view
|

Re: How can I find where one word is close to another word?

Lifepillar
In reply to this post by Adrian Keister
On 2020-07-25, Adrian Keister <[hidden email]> wrote:

>
>
> As most people on this forum are likely aware, searching for a word is
> straight-forward enough. If I want to find occurrences of the word 'arc', I
> can type / arc , with spaces around the three letters, to find basic
> occurrences of the word (ignoring punctuation). But suppose I want to find
> where two words are close together, say, within ten words? Here's an
> example:
>
> Now is the time for all good men to come to the aid of their country.
>
> In this test, I want to find all occurrences where the word 'aid' is within
> ten words of the word 'country'. How can I do that in Vim?

Another idea, based on \%V (see `:help %V`):

1. Search for some text, e.g.:

    /country<Enter>

2. Move back the desired amount, e.g., 10 WORDS:

    10B

3. Visually select the range to be searched, e.g. 20 WORDS:

    v20W

4. Return to Normal mode and search within the previously selected range:

   <Esc>/\%Vaid

5. To search for the next match, move forward (10W) and repeat.

Putting all that in a couple of macros, you could do:

qa/country<Enter>10Bv20W<Esc>/\%Vaid<Enter>q
qb10W@aq

Now you may type @b repeatedly to perform your search.

Hope this helps,
Life.

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/rfjeu5%24179l%241%40ciao.gmane.io.
Reply | Threaded
Open this post in threaded view
|

Re: How can I find where one word is close to another word?

Adrian Keister
In reply to this post by Tim Chase
Tim,

I haven't tried your code, yet, but I was wondering about this followup: 

Would it be possible to essentially parametrize your command in vimrc, so that I could do something like this?

/ps/firstword/secondword/distance

I'm using 'ps' for 'proximity search', but if that's already a taken command, we'd have to make it something else. 

Many thanks for your help!

Cheers,
Adrian

On Saturday, July 25, 2020 at 8:41:55 PM UTC-5, Tim Chase wrote:
On 2020-07-25 17:54, Adrian Keister wrote:
> There's an answer on the Stack Exchange site. Does that method work
> also?

That method finds only the case in which you have "aid" *followed by*
"country", so if you have

  "This country needs all good men to come to her aid."

it won't find that even though "country" and "aid" are within 10
words of each other.

You might recognize that it's pretty similar to the first half of my
2nd answer:  "term1(N optional words)term2" which I then swap around
with "or term2(N optional words)term1".

So if you only need "X with Y following it within N words", that's
an easy solution.  If you need to allow for arbitrary ordering of the
words, you need a bit more such as either of my suggestions.

-tim



--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/b24310f6-98e1-44a1-b35a-cbeedc810de2o%40googlegroups.com.