5

Is there a way to do:

output | grep "string1" | grep "string2" 

BUT with awk, WITHOUT PIPE?

Something like:

output | awk '/string1/ | /string2/ {print $XY}'

Result should be subset of matches, if tha makes sense.

RiddleMeThis
  • 209
  • 1
  • 9
  • 1
    Have a look at the accepted answer here: [grep with logic operators](https://unix.stackexchange.com/a/177524/65304) – steeldriver Dec 30 '20 at 14:50
  • just a `|` missing : `awk '/string1/ || /string2/ {print $XY}' ` – Archemar Dec 30 '20 at 14:50
  • 3
    @Archemar that’s not quite the same though: `||` will match any line with either “string1” or “string2”, whereas the `grep`s only match lines with both (so `&&` in AWK). – Stephen Kitt Dec 30 '20 at 14:56
  • my bad, I read too quickly once again ... – Archemar Dec 30 '20 at 14:58
  • its supposed to mean column number e.g. $0, $1 etc. – RiddleMeThis Dec 30 '20 at 15:35
  • _"Result should be subset of matches,"_ -- I guess the technical word is ["intersection"](https://en.wikipedia.org/wiki/Intersection_(set_theory)), but it might be better to just spell out what you mean. :) – ilkkachu Dec 31 '20 at 10:50
  • To be clear `grep "string1" | grep "string2"` does **not** grep for 2 strings, it greps for 2 regexps.You'd have to add `-F` to your grep commands to grep for 2 strings and then the awk answer you accepted would be wrong. – Ed Morton Jan 02 '21 at 18:30

2 Answers2

11

The default action with awk is to print, so the equivalent of

output | grep string1 | grep string2

is

output | awk '/string1/ && /string2/'

e.g.

$ cat tst
foo
bar
foobar
barfoo
foothisbarbaz
otherstuff

$ cat tst | awk '/foo/ && /bar/'
foobar
barfoo
foothisbarbaz
Stephen Harris
  • 42,369
  • 5
  • 94
  • 123
  • 1
    Accepting this answer because of the extra example/ proof – RiddleMeThis Dec 30 '20 at 16:06
  • That is the equivalent of the pipeline the OP provided but if the OP actually wants to match 2 **strings** instead of 2 regexps then it'd be `awk 'index($0,"string1") && index($0,"string2")` – Ed Morton Jan 02 '21 at 18:31
5

If you want awk to find lines that match both string1 and string2, in any order, use &&:

 output | awk '/string1/ && /string2/ {print $XY}'

If you want to match either string1 or string2 (or both), use ||:

 output | awk '/string1/ || /string2/ {print $XY}'
terdon
  • 234,489
  • 66
  • 447
  • 667
  • 1
    Just to note, for anyone who stumbles upon this, what I exactly did was: ps aux | awk ... to keep awk from showing in the result I had to do awk /[s]tring/. Its the same trick used for grep. – RiddleMeThis Dec 30 '20 at 15:12
  • 2
    I think the `{print $XY}` thing is something like a placeholder that the OP thought would be useful/necessary. I believe it is better out of the answer since it doesn't make much sense. – Quasímodo Dec 30 '20 at 15:34
  • @Quasímodo it makes perfect sense: it is a placeholder for "print field number N" and including it shows what the correct syntax would be, so it can easily be adapted by future users. – terdon Jan 01 '21 at 14:37