Pipe Contents Into Grep

I have a command which outputs groups I'm a member of as text:

$ groups
dbadmin hdpcl3 stargroup9 jorgesgroup ...

I would like to check if this output contains a group I have in mind. I tried:

$ groups > mygroups.txt
$ grep -R "stargroup9" mygroups.txt
stargroup9

This works, but I'd like to do it in one line without creating a temporary file. One way that would be neat, as it would generalize, would be to know how to:

$ groups | grep -R "stargroup9" .

Where '.' means put the input here, like in R's dplyr/magrittr syntax:

> my_species %>% filter(iris, Species == .)
1

1 Answer

To make grep process its stdin you should invoke it without file (or directory) names as operands. This is a straightforward, although not the best solution:

groups | grep "stargroup9"

This is way better:

groups | grep -E '(^| )stargroup9( |$)'

where (^| ) matches the beginning of the line or a space character, ( | $) matches a space character or the end of the line; so e.g. a group named stargroup98765 is not a match.

-E uses extended regular expressions. As a basic regular expression (without -E) the pattern should look like this: \(^\| \)stargroup9\( \|$\) (and it should be single-quoted). I used -E because the pattern is more readable this way.

You may encounter an advice with a pattern like \bstargroup9\b, where \b anchors at word boundary (or grep -w stargroup9 which is eqivalent). Do not use this approach here. The problem is group names can contain - but this character (as far as \b is concerned) separates words. In effect the pattern can match e.g. a group named stargroup9-123foo. If you are in this group but not in stargroup9, the pattern with \b will mislead you (and the same applies to grep -w).

In a script you may want to check if you're a member without printing any output from grep. Use -q to make the command quiet. Its exit status is enough. Examples:

groups | grep -qE '(^| )stargroup9( |$)' && do_something
if groups | grep -qE '(^| )stargroup9( |$)'; then …

What is wrong with your approach?

grep -R reads files under specified directories recursively. The option changes nothing if you specify only file(s) (i.e. non-directory).

If you want grep to read from its stdin (like in groups | grep …), you cannot specify any operands (files or directories). Then you cannot use -R because without operands the option makes grep process the current directory, not stdin.

Side note: -R is not specified by POSIX, therefore not portable.


I think groups may produce output in a form of

username : group1 group2 …

especially if you specify the user name (groups username). If so, you may want to remove everything excessive first. Since : cannot appear anywhere else (it's not a valid character in user/group name), the following command should work regardless of whether groups generates output starting with username : or not:

groups username | sed 's/.*: //' | grep -E '(^| )groupname( |$)'
2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like