6

I explain my problem on Ubuntu 16.04 with the following example: The file is:

# cat file
aaa
aaaxxx
aaaxxx*aaa
aaa=aaaxxx
bbbaaaccc
aaaddd/aaaxxx

I want to display all lines which contain aaa but not in the only combination of aaaxxx. I want an output like this:

# grep SOMETHING-HERE file …
aaa
aaaxxx*aaa (second aaa is the hit)
aaa=aaaxxx (first aaa is the hit)
bbbaaaccc (aaa in any other combination but not aaaxxx)
aaaddd/aaaxxx (similar to above)

I tried things like grep -v aaaxxx file | grep aaa which results:

aaa
bbbaaaccc

or

# egrep -P '(?<!aaaxxx )aaa' file
grep: die angegebenen Suchmuster stehen in Konflikt zueinander (the pattern are in contradiction)

Is there any (simple) possibility? Of course it doesn’t need to be grep. Thanks

7
  • "but in the only combination of aaaxxx" - don't you mean except aaaxxx?
    – Byte Commander
    Nov 3, 2016 at 20:02
  • So, you want all lines that contain aaa followed by anything except xxx?
    – terdon
    Nov 3, 2016 at 20:02
  • @Byte Commander Sorry I forgot a not. I updated the question
    – musbach
    Nov 3, 2016 at 20:06
  • @terdon not if the line only contain only aaaxxx. However I want lines with aaa and aaaxxx. Puh!
    – musbach
    Nov 3, 2016 at 20:08
  • 1
    @musbach so you want all lines matching aaa, including those matching aaaxxx but not lines that have only aaaxxx. So, aaa is fine, aaaxxxfoo is fine, but aaaxxx alone should be skipped?
    – terdon
    Nov 3, 2016 at 20:21

1 Answer 1

8

It's straightforward using a perl-style lookahead operator - available in grep's Perl Compatible Regular Expression (PCRE) mode using the -P switch:

$ grep -P 'aaa(?!xxx)' file
aaa
aaaxxx*aaa
aaa=aaaxxx
bbbaaaccc
aaaddd/aaaxxx

(bold formatting in the output indicates the matched parts highlighted by grep)


Although the zero-length lookahead is convenient, you could achieve the same output using GNU Extended Regular Expression (ERE) syntax, for example by matching aaa followed by up to 2 x characters followed by a non-x character or end-of-line i.e.

grep -E 'aaax{0,2}([^x]|$)' file

or even using GNU basic regular expression (BRE) syntax

grep 'aaax\{0,2\}\([^x]\|$\)' file

which match as

aaa
aaaxxx*aaa
aaa=aaaxxx
bbbaaaccc
aaaddd/aaaxxx
6
  • Blegh, few seconds faster than me...
    – Byte Commander
    Nov 3, 2016 at 20:05
  • Hope you don't mind me highlighting the output a bit.
    – Byte Commander
    Nov 3, 2016 at 20:08
  • @ByteCommander no problem, not smart enough to do it myself ;) Nov 3, 2016 at 20:10
  • @musbach I don't understand. This doesn't do what you seem to want. It will not match aaaxxxfoo for example.
    – terdon
    Nov 4, 2016 at 9:56
  • 1
    @musbach or you can use the -x or -w flags for grep. There are various things you can do, but you need to explain exactly what you need when asking. For the specific case in your comment, you could just do grep -P 'VAR(?!A|B)'.
    – terdon
    Nov 4, 2016 at 19:13

You must log in to answer this question.

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