13

I am trying to find out how I can use:

grep -i

With multiple strings, after using grep on another command. For example:

last | grep -i abc
last | grep -i uyx

I wish the combine the above into one command, but when searching on the internet I can only find references on how to use multiple strings with grep, when grep is used with a file, and not a command. I have tried something like this:

last | grep -i (abc|uyx)

Or

last | grep -i 'abc|uyx'

But that doesn't work. What is the correct syntax to get the results I epxect?

Thanks in advance.

  • "I can only find references on how to use multiple strings with grep, when grep is used with a file, and not a command" - it does not matter where the input for grep comes from, be it a file or a command. The options are still the same. – Panki Mar 17 '22 at 14:37
  • 2
    Or to make it more clear: last | grep -i -e abc -e xyz – Panki Mar 17 '22 at 14:40
  • 2
    ... grep -i 'abc|uyx' doesn't work because | is not an alternation operator in basic regular expression (BRE); you'd need grep -Ei 'abc|uyx' (-E for extended regular expression mode) – steeldriver Mar 17 '22 at 14:49

2 Answers2

19

Many options with grep alone, starting with the standard ones:

grep -i -e abc -e uyx
grep -i 'abc
uyx'
grep -i -E 'abc|uyx'

With some grep implementations, you can also do:

grep -i -P 'abc|uyx' # perl-like regexps, sometimes also with
                     # --perl-regexp or -X perl
grep -i -X 'abc|uyx' # augmented regexps (with ast-open grep) also with
                     # --augmented-regexp
grep -i -K 'abc|uyx' # ksh regexps (with ast-open grep) also with
                     # --ksh-regexp
grep -i 'abc\|uyx'   # with the \| extension to basic regexps supported by
                     # some grep implementations. BREs are the
                     # default but with some grep implementations, you
                     # can make it explicit with -G, --basic-regexp or
                     # -X basic

You can add (...)s around abc|uyx (\(...\) for BREs), but that's not necessary. The (s and )s, like | also need to be quoted for them to be passed literally to grep as they are special characters in the syntax of the shell language.

Case insensitive matching can also be enabled as part of the regexp syntax with some grep implementations (not standardly).

grep -P '(?i)abc|uyx' # wherever -P / --perl-regexp / -X perl is supported
grep -K '~(i)abc|uyx' # ast-open grep only
grep -E '(?i)abc|uyx' # ast-open grep only
grep '\(?i\)abc|uyx'  # ast-open grep only which makes it non-POSIX-compliant

Those don't really bring much advantage over the standard -i option. Where it could be more interesting would be for instance if you want abc matching to be case sensitive and uyx not, which you could do with:

grep -P 'abc|(?i)uyx'

Or:

grep -P 'abc|(?i:uyx)'

(and equivalent variants with other regexp syntaxes).

The standard equivalent of that would look like:

grep -e abc -e '[uU][yY][xX]'

(bearing in mind that case-insensitive matching is often locale-dependent; for instance, whether uppercase i is I or İ may depend on the locale according to grep -i i).

2
grep 'abc\|uyx'
egrep 'abc|uyx'
alecxs
  • 564