grep可以返回true / false还是有其他方法


130

作为此脚本的一部分,我需要能够检查给定的第一个参数是否与文件的第一个单词匹配。如果是这样,则退出并显示错误消息;如果没有,则将参数附加到文件中。我了解如何编写该if语句,但不了解如何grep在脚本中使用。我知道这grep看起来像这样

grep ^$1 schemas.txt

我觉得这应该比我做起来容易得多。

我在if语句中收到“参数过多”的错误。我摆脱了之间的空间grep -q,然后得到了预期的错误二进制运算符。

if [ grep -q ^$1 schemas.txt ]
then
        echo "Schema already exists. Please try again"
        exit 1
else
        echo "$@" >> schemas.txt
fi

1
失去[…… ],它将起作用。虽然您可能想引用您的模式:if grep -q "^$1" schemas.txt; then …
derobert 2012年

:使用bash的“组命令”功能一个在线解决方案stackoverflow.com/questions/6550484/...
特雷弗·博伊德·史密斯

Answers:


186

grep如果发现某物(零)与未发现任何物(非零),则返回不同的退出代码。在一条if语句中,零退出代码被映射为“ true”,非零退出代码被映射为false。此外,grep具有一个-q参数,不输出匹配的文本(仅返回退出状态代码)

因此,您可以像这样使用grep:

if grep -q PATTERN file.txt; then
    echo found
else
    echo not found
fi

快速说明一下,当您执行if [ -z "$var" ]…时,[实际上就像grep 一样,实际上是您正在运行的命令。在我的系统上是/usr/bin/[。(从技术上讲,您的外壳可能内置了它,但这是一种优化。它的行为就像是一条命令一样)。它以相同的方式工作,[返回零退出代码为true ,返回非零退出代码为false。(test是同样的事情[,除了关闭]


为什么if语句不需要括号?我没有它就可以工作,但是不明白为什么。我还能在没有括号的情况下嵌套它吗?
劳伦(Lauren)2012年

@Lauren您错过了快速笔记吗?[不是if语法的一部分,它(从概念上来说)是您正在运行的命令,就像grep一样
derobert 2012年

2
@Lauren您不会在[内使用grep,而是使用一个或另一个,这取决于要检查的条件。(您可以在if,btw,if中使用任何命令,只要检查退出代码。)…嗯,我想您可能想出了在[中使用grep的原因,但这将是一个相当复杂的脚本及其不是正常的事情。
derobert 2012年

3
仅供参考,运行ls -l /usr/bin/\[man [看到它[是一个与其他任何程序一样的程序,它看起来像一个语法元素-这应该使它变得显而易见并且易于理解。(为方便起见,[它也是bash,dash和其他内置的-但这仍然是命令)。也可以尝试type -all [bash。
cas 2012年

1
@AlexanderCska如果要grep打印匹配的行(例如,将它们通过管道传输到某处),则省略-q,该选项告诉grep保持安静(不打印匹配的行)。
derobert

47

另一个简单的方法是使用grep -c

输出(不返回退出代码),即与模式匹配的行数,因此,如果不匹配,则为0,如果匹配,则为1或更多。

因此,如果您想检查模式是否匹配3次或更多次,则可以执行以下操作:

if [ "$(grep -c "^$1" schemas.txt)" -ge 3 ]; then
  ...

17
更准确地说,如果仅发现一次,它将输出 1。要输出1,而不考虑找到的匹配项数量,请grep -cim1改用。
manatwork 2013年

此方法也可以用于区分grep错误和grep“找到0次模式”。(尽管没有确切的if语句,但我认为需要一个变量)
Evan Benn


0

如果我们想捕获文件的第一个单词,则需要添加-zw到grep中

if grep -qzw "^$1" file
then 
   ... 
else 
   ... 
fi

没有-z我们,我们得到一行的第一个单词。没有-w我们,我们会得到部分的话。


-2

如果要在方括号中使用它,可以执行以下命令

if [ `grep -q PATTERN file.txt` ]; then
    echo found
else
    echo not found

此逻辑适用于所有命令,只需将命令放在反引号内(选项卡上方的按钮或Esc按钮的下方或1按钮的左侧)


1
您需要用引号引起来`grep -q PATTERN file.txt`,否则将使用split + glob运算符,这对于包含字符$IFS或通配符的任何输出都会引起问题。更一般而言,[ "`cmd`" ]如果cmd在stdout上至少输出一条非空行,则返回true (如果输出NUL字节,则可能会出现问题)。这意味着外壳将必须将整个输出存储在内存中并等待其完成。if cmd | grep -q .在这方面,最好使用替代方法。
斯特凡Chazelas

这个命令根本没有任何意义。-q开关的目的是抑制 grep的输出。您的意思是:在file.txt中检查PATTERN,抑制任何输出,然后根据是否找到PATTERN设置返回状态。然后,忽略返回状态,获取命令输出(我们被迫为空),应用分词和文件glob扩展(根本不包含任何参数),然后仅使用一个参数运行[(aka test)命令,即,]-然后,由于这将导致错误,请回显“未找到”。@StéphaneChazelas,我想念什么吗?
通配符

1
@Wildcard,您是对的,我显然忽略了-q。该注释对有意义[ `grep PATTERN file.txt ` ],但如注释中所暗示,[ "`grep -n PATTERN file.txt`" ]如果PATTERN只能匹配空行,则更好。虽然这当然是if grep -q PATTERN file.txt您想要的。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.