Quantcast

Search a pattern and provide a context (few lines above and below)

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Search a pattern and provide a context (few lines above and below)

Zarko Coklin
Hello everyone!

I am trying to find a command to achieve a search with a context. Let'
say I have a file containing following lines:

1. dog
2. cat                 // <- I want to keep this line and one line
above and one line below
3. mouse
4. cow
5. horse
6. dolphin
7. whale
8. cat               // <- I want to keep this line and one line above
and one line below
9. sheep
10. bat


I would like to find all the lines containing "cat" and preserve a
line above and below. The rest rest of lines should be deleted. So,
when I run the command my output should look like following:

1. dog
2. cat
3. mouse
7. whale
8. cat
9. sheep


I believe the following command does something similar to what I need

:g/192.168.4.2:5120 ->/z#.3

The only problem is that unwanted lines are not deleted and I can only
browse the file but not save/copy the result.

Anyone knows the answer?

Thanks in advance!

--
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Search a pattern and provide a context (few lines above and below)

Zarko Coklin
Sorry the command in my previous post should had been:

 :g/cat/z#.3

--
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Search a pattern and provide a context (few lines above and below)

Ben Fritz
On Tuesday, April 10, 2012 4:51:35 PM UTC-5, Zarko Coklin wrote:
> Sorry the command in my previous post should had been:
>
>  :g/cat/z#.3


You could use :redir to put the output of this command in a new file, variable, or register.

Or, more to my taste, don't delete stuff, just fold it away:

http://vim.wikia.com/wiki/Folding_with_Regular_Expression

--
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Search a pattern and provide a context (few lines above and below)

Tim Chase
In reply to this post by Zarko Coklin
On 04/10/12 16:49, Zarko Coklin wrote:

> 1. dog
> 2. cat       //<- I want to keep this line and one line above and one line below
> 3. mouse
> 4. cow
> 5. horse
> 6. dolphin
> 7. whale
> 8. cat      //<- I want to keep this line and one line above and one line below
> 9. sheep
> 10. bat

I think to do this, it would be easiest to do some sort of
decorate/process/undecorate pass such as

   :g/cat/sil! -,+>
   :v/^\s/d
   :%<

which works with your example (where everything is
left-justified).  Your decoration and deletion-of-undecorated
could be any other marker such as

   :%s/.*cat/XXX&
   :v/^XXX/d
   :%s/^XXX

Alternatively, you can do it in one pass:

   :v/cat\|.*\n.*cat\|\%(cat.*\n\)\@<=./d

which basically just enumerated the 3 conditions on which a line
can match ("cat" is on the line, there's stuff followed by a
newline followed by stuff containing "cat", or you assert that
the previous line contains "cat").

The first one scales better to greater numbers of context lines
(you can easily adjust the number of lines backwards & forwards,
or do the adjustment with searches rather than relative
line-number offsets); while for your particular case, the
all-in-one might be easier.

> I believe the following command does something similar to what I need
>
> :g/192.168.4.2:5120 ->/z#.3

It warms my grey-beard heart to see other people employing the
very underutilized :z family of commands. :-)

-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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Search a pattern and provide a context (few lines above and below)

Zarko Coklin
Thanks Tim!

I think I found somewhere on the Internet an example how to use a 'z'
comnand. If I am not mistaken the author signed himself with "tim" :-)

BTW, my example is simplified and the solution should get the line
which has a pattern (could be at the beginnig, middle or end). Which
if your suggested solutions would work best? Also explain how to tweak
number of lines above/below.

Thanks!
Z

On 2012-04-10, at 7:39 PM, Tim Chase <[hidden email]> wrote:

> On 04/10/12 16:49, Zarko Coklin wrote:
>> 1. dog
>> 2. cat       //<- I want to keep this line and one line above and one line below
>> 3. mouse
>> 4. cow
>> 5. horse
>> 6. dolphin
>> 7. whale
>> 8. cat      //<- I want to keep this line and one line above and one line below
>> 9. sheep
>> 10. bat
>
> I think to do this, it would be easiest to do some sort of decorate/process/undecorate pass such as
>
>  :g/cat/sil! -,+>
>  :v/^\s/d
>  :%<
>
> which works with your example (where everything is left-justified).  Your decoration and deletion-of-undecorated could be any other marker such as
>
>  :%s/.*cat/XXX&
>  :v/^XXX/d
>  :%s/^XXX
>
> Alternatively, you can do it in one pass:
>
>  :v/cat\|.*\n.*cat\|\%(cat.*\n\)\@<=./d
>
> which basically just enumerated the 3 conditions on which a line can match ("cat" is on the line, there's stuff followed by a newline followed by stuff containing "cat", or you assert that the previous line contains "cat").
>
> The first one scales better to greater numbers of context lines (you can easily adjust the number of lines backwards & forwards, or do the adjustment with searches rather than relative line-number offsets); while for your particular case, the all-in-one might be easier.
>
>> I believe the following command does something similar to what I need
>>
>> :g/192.168.4.2:5120 ->/z#.3
>
> It warms my grey-beard heart to see other people employing the very underutilized :z family of commands. :-)
>
> -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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Search a pattern and provide a context (few lines above and below)

Tim Chase
On 04/10/12 19:04, Zarko Coklin wrote:
> I think I found somewhere on the Internet an example how to use a 'z'
> comnand. If I am not mistaken the author signed himself with "tim" :-)

Ah, that would make sense...I'm likely the guilty party.

> BTW, my example is simplified and the solution should get the line
> which has a pattern (could be at the beginnig, middle or end). Which
> if your suggested solutions would work best? Also explain how to tweak
> number of lines above/below.
>
>>   :v/cat\|.*\n.*cat\|\%(cat.*\n\)\@<=./d

If you just want the line with one-before and one-after, the
above one works nicely.  If you want to do an arbitrary number of
lines above/below, the decorate/process/undecorate is far friendlier

  :g/cat/sil! -8,+4s/^/XXX
  :v/^XXX/d
  :%s/^XXX

would give you 8 lines of context before and 4 lines of context
afterward.  Note that, if these ranges overlap (such that 8 lines
before ends up within the 4 lines after) you'll get them
decorated twice, so you might have to use that last ":%s/^XXX"
multiple times.  In this case "XXX" is some arbitrary text that
never appears at the beginning of a line in your actual document.

If you want search bracketing instead of fixed-line bracketing,
such as if you had C-like code:

   int foo(bar) {
      aaa;
      bbb;
      cat;
      ccc;
      ddd;
   }

you can change the absolute ranges ("-8,+4") to relative search
ranges like

   g/cat/sil! ?^\<.*{$?;/^}/s/^/XXX

which is the range from "search backwards for a line that starts
with a Word character in the first column and has a '{' at the
end of the line" through "then, from there, search forward until
you find a '}' as the first character of the line" and then put
"XXX" in front of each line.

-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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Search a pattern and provide a context (few lines above and below)

Tim Chase
On 04/10/12 22:19, Zarko Coklin wrote:
> I am still not clear whether I should admire people who know
> these things like some divine entities or judge them for not
> having the life :-)

It's just like playing with Legos...you have various parts that
fit together in well-defined ways, and you just put them together
so that they do what you want. :)

-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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Search a pattern and provide a context (few lines above and below)

Zarko Coklin
I actually combined input from both Tim and Ben and came up with a hybrid solution. It uses a global command and redirect lines into a new file and goes like this:

:redir @* |g/cat/sil! -3,+4 |redir END | redir >> results.txt

Such solution will find all lines where "cat" is mentioned and copy a block of lines starting from 3 lines above and 4 lines below. The result is placed into a file named "results.txt". I like one liner solutions and this works faster on larger files.

--
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
Loading...