0

I would like to grep a file to find all instances of the text fn1 that don't have the word call in front of it and print out four lines before and after the matches (even if the surrounding lines have the word call in them). I tried

grep -A 4 -B 4 '[^call].+fn1'

but it doesn't get any matches (presumably because of the [^call]). I cannot just use -v and pipe that that to another grep or vice versa because I want to see the surrounding lines of text. I guess I could use -v on call, pipe that to grep fn1 and then pipe those lines to another instance of grep that matches the whole lines with context but that seems ugly and might be really slow if there are a lot of matches.

This seems like it should be simple, but I'm not sure. Any help?

EDIT:

Sample data

main code
main code
more main code
call fn1(ii, jj)
even more main code
call fn2
still more main code

function fn1
call fn3
fn1 code
more fn1 code

I would like grep to retutn

call fn2
still more main code

function fn1
call fn3
fn1 code
more fn1 code

I want it to show me all the instances where fn1 is used except when it's being called and I don't want to miss other functions that are being called within the context.

7
  • 3
    can you show your input data??
    – Hackaholic
    Dec 3, 2014 at 21:50
  • 1
    some sample data w/ this Q would probably make light work of getting it resolved.
    – slm
    Dec 4, 2014 at 2:39
  • Thanks for the suggestion. I added an example of what I'm looking for. Dec 4, 2014 at 18:55
  • 1
    To clarify: [^call] does not mean everything except the word call. It means any character except c, a or l.
    – muru
    Dec 4, 2014 at 18:55
  • Similar/same question. Better answers though. unix.stackexchange.com/questions/96480/…
    – gaoithe
    Mar 31, 2016 at 14:21

1 Answer 1

2

To negate regular expressions is not easy. You could use negative lookbehinds:

$ grep -C4 -P '(?<!call).*fn1' test.txt 
5-even more main code
6-call fn2
7-still more main code
8-
9:function fn1
10-call fn3
11-fn1 code
12-more fn1 code

This grep uses Perl-style regular expressions (-P) to look for any instance of fun not preceded by call. And you can combine -A4 -B4 to get -C4.

5
  • that doesn't work ?
    – gaoithe
    Mar 31, 2016 at 14:13
  • @gaoithe are you telling me or asking me? Does your grep support PCRE?
    – muru
    Mar 31, 2016 at 14:14
  • Yes. perl-style supported. That doesn't work for me. I am asking does it work for you? This works for me: grep -B4 -A4 -P '^(?:(?!call)).*fn1' sample.txt
    – gaoithe
    Mar 31, 2016 at 14:20
  • 1
    @gaoithe very strange, you're right. I'll have to test around to see how I got this to work.
    – muru
    Mar 31, 2016 at 14:35
  • your answer is along the right lines, see unix.stackexchange.com/questions/96480/… good explanation. Using "negative lookahead assertion". They describe it as "The main thing of note here is that (?:(?!STRING).)* is to STRING as [^CHAR]* is to CHAR".
    – gaoithe
    Mar 31, 2016 at 14:37

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.