8

Let's say I have a file containing following two lines:

2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
2014-05-05      09:12:17    /aa/bbbb/cccccc?dddddddd    16767 

I need to get the line containing the pattern /aa/bbbb/cccccc only, I don't need the second line containing extra characters i.e. ?dddddddd. Now when I tried

grep '/aa/bbbb/cccccc' file

Then both of the lines being selected. I need the full line so grep -o could not be a solution.

What could be the possible solution using grep so that only the first line gets selected based on the search pattern?

0

3 Answers 3

10

The simplest way would be to add a space after your pattern:

$ grep '/aa/bbbb/cccccc ' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Or, to match all kinds of whitespace:

$ grep  '/aa/bbbb/cccccc[[:space:]]' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Or

$ grep -P '/aa/bbbb/cccccc\s+' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Or, with a positive lookahead:

$ grep -P '/aa/bbbb/cccccc(?=\s)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Or, with a negative lookahead:

$ grep -P '/aa/bbbb/cccccc(?!\S)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Or you can reverse the match:

$ grep  -v 'c?' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Or, to also match lines that contain nothing but your pattern (no trailing whitespace):

grep -P '/aa/bbbb/cccccc(\s+|$)' file 
grep -E '/aa/bbbb/cccccc(\s+|$)' file 

Or, you can just use a small script:

  • In awk:

    $ awk '$3=="/aa/bbbb/cccccc"' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

    Or, if you don't know which field your pattern is in

    $ awk '{for(i=1;i<=NF;i++){if($i=="/aa/bbbb/cccccc"){print}}}' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
  • In Perl

    $ perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
2
  • @terdon in grep -v 'c?' file why you don't use grep -v '?' file because file has only two lines in it. Nov 16, 2014 at 16:49
  • @KasiyA true, I just wanted to keep a bit of the pattern. You're quite right though, in this particular case, grep -v '?' would be enough.
    – terdon
    Nov 16, 2014 at 18:37
7

Try the below grep command which uses -P (Perl-regexp) parameter.

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S) This negative lookbehind asserts that the character which preceeds the string /aa/bbbb/cccccc would be any but not a non-space character.

  • (?!\S) Negative lookahead asserts that the character following the match would be any but not a non-space character.

Another grep,

 grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file

Through python,

script.py

#!/usr/bin/python3
import re
import sys
file = sys.argv[1]
with open(file, 'r') as f:
    for line in f:
        for i in line.split():
            if i == "/aa/bbbb/cccccc":
                print(line, end='')

Save the above code in a file and name it as script.py. Then execute the above script by

python3 script.py /path/to/the/file/you/want/to/work/with
5
  • Thanks man. Btw can this be done using normal/extended regex rather than perl regex?
    – heemayl
    Nov 16, 2014 at 12:46
  • 1
    like terdon posted, you could simply grep '/aa/bbbb/cccccc ' file Nov 16, 2014 at 12:54
  • But the above won't print the lines which has only /aa/bbbb/cccccc string. Nov 16, 2014 at 13:19
  • You can match that too with grep -E '/aa/bbbb/cccccc(\s+|$)' file
    – terdon
    Nov 16, 2014 at 18:51
  • yep, like this grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file Nov 17, 2014 at 5:27
2

To complement @AvinashRaj's answer, you can use also command like this.

grep -P '/a+/b+/c+(?!\S)' file

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .