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

grep ^ schemas.txt


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

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

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


评论

丢掉[…],它将起作用。虽然您可能想引用模式:if grep -q“ ^ $ 1” schemas.txt;然后...

使用Bash的“组命令”功能的一线解决方案:stackoverflow.com/questions/6550484/…

Bash oneliner。如果在文件content.txt中找到字符串“ foo”,则运行命令work.sh,否则不执行任何操作:cat content.txt | grep“ foo” && work.sh

#1 楼

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语句不需要括号?我没有它就可以工作,但是不明白为什么。我还能在没有括号的情况下嵌套它吗?

–劳伦
2012-09-18 18:47

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

–德罗伯特
2012年9月18日19:06

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

–德罗伯特
2012-09-18 19:21



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

–cas
2012-09-18 22:56

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

–德罗伯特
19年7月22日在16:00

#2 楼

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

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

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

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


评论


更准确地说,如果仅发现一次,它将输出1。要输出1(无论找到的匹配项多少),请改用grep -cim1。

–manatwork
13年4月29日在10:26

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

–埃文·本恩
19年4月3日在5:27

grep -cim1的说明:-c表示打印计数,-i表示不区分大小写(因此,如果不需要,请删除此选项),-m表示在此行匹配之后停止读取。因此,它实际上意味着grep --count --ignore-case --max-count = 1。

–提交
20-10-6在4:29



#3 楼

我知道我为此迟到了,但是我喜欢这个简短的版本:

grep -q ^ schemas.txt && echo "Schema already exists. Please try again" || echo "$@" >> schemas.txt


#4 楼

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

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


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

#5 楼

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

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


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

评论


您需要引用`grep -q PATTERN file.txt`,否则将应用split + glob运算符,这将对包含$ IFS字符或通配符的任何输出产生问题。更一般而言,如果cmd在stdout上输出至少一根非空行,则[“`cmd`”]将返回true(如果输出NUL字节,则可能会出现问题)。这意味着外壳将必须将整个输出存储在内存中并等待其完成。使用if cmd | grep -q。在这方面可能更可取。

–StéphaneChazelas
16年8月24日在13:01

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

–通配符
16 Sep 16 '22:51

@Wildcard,您是对的,我显然忽略了-q。该注释对[`grep PATTERN file.txt`]有意义,但正如注释中所暗示的,如果PATTERN仅可匹配空行,则[“`grep -n PATTERN file.txt`”]会更好。虽然这里当然是您想要的grep -q PATTERN file.txt。

–StéphaneChazelas
16-09-17在6:47