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?

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
| improve this answer | |
  • Thanks man. Btw can this be done using normal/extended regex rather than perl regex? – heemayl Nov 16 '14 at 12:46
  • 1
    like terdon posted, you could simply grep '/aa/bbbb/cccccc ' file – Avinash Raj Nov 16 '14 at 12:54
  • But the above won't print the lines which has only /aa/bbbb/cccccc string. – Avinash Raj Nov 16 '14 at 13:19
  • You can match that too with grep -E '/aa/bbbb/cccccc(\s+|$)' file – terdon Nov 16 '14 at 18:51
  • yep, like this grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file – Avinash Raj Nov 17 '14 at 5:27
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
    
| improve this answer | |
  • @terdon in grep -v 'c?' file why you don't use grep -v '?' file because file has only two lines in it. – αғsнιη Nov 16 '14 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 '14 at 18:37
2

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

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

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.