我有一个命令,可以以文本形式输出我所属的组:
$ groups
dbadmin hdpcl3 stargroup9 jorgesgroup ...
我想检查一下此输出是否包含我想要的组。我试过:
$ groups > mygroups.txt
$ grep -R "stargroup9" mygroups.txt
stargroup9
这可行,但我想在一行中完成此操作而不创建临时文件。一种简洁的方法是知道如何:
$ groups | grep -R "stargroup9" .
其中 '.' 表示将输入放在此处,例如R 的 dplyr/magrittr句法:
> my_species %>% filter(iris, Species == .)
答案1
要使grep
进程成为其 stdin,您应该在不使用文件(或目录)名称作为操作数的情况下调用它。这是一个简单但不是最佳的解决方案:
组 | grep "stargroup9"
这样更好:
groups | grep -E '(^| )stargroup9( |$)'
其中(^| )
匹配行首或空格字符,( | $)
匹配空格字符或行尾;因此例如名为的组stargroup98765
不匹配。
-E
使用扩展正则表达式。作为基本正则表达式(不带-E
),模式应如下所示:(\(^\| \)stargroup9\( \|$\)
并且应使用单引号)。我之所以使用,-E
是因为这种方式的模式更具可读性。
您可能会遇到一个建议,其模式类似于\bstargroup9\b
,其中\b
锚定在单词边界(或grep -w stargroup9
是等效的)。请勿在此处使用此方法。问题是组名可以包含,-
但此字符(就此而言\b
)分隔单词。实际上,该模式可以匹配名为 的组stargroup9-123foo
。如果您在这个组中但不在 中stargroup9
,则模式\b
会误导您(同样适用于grep -w
)。
在脚本中,您可能希望检查自己是否是成员,而不打印 的任何输出grep
。使用-q
使命令安静。它的退出状态就足够了。示例:
groups | grep -qE '(^| )stargroup9( |$)' && do_something
if groups | grep -qE '(^| )stargroup9( |$)'; then …
你的方法有什么问题?
grep -R
递归读取指定目录下的文件。如果仅指定文件(即非目录),则该选项不会发生任何变化。
如果grep
要从其 stdin 读取(如 中所示groups | grep …
),则不能指定任何操作数(文件或目录)。然后您无法使用,-R
因为没有操作数,该选项会使grep
进程成为当前目录,而不是 stdin。
旁注:-R
未由 POSIX 指定,因此不可移植。
我认为groups
可能会产生以下形式的输出
username : group1 group2 …
尤其是如果您指定用户名 ( groups username
)。如果是这样,您可能需要先删除所有多余的内容。由于不能出现在其他任何地方(它不是用户/组名中的有效字符),因此无论是否生成以 开头的输出,:
以下命令都应该有效:groups
username :
groups username | sed 's/.*: //' | grep -E '(^| )groupname( |$)'