如何使用Bash检查文件是否包含特定字符串

417

我想在Bash中检查文件是否包含特定的字符串。我使用了这个脚本,但它不起作用:

 if [[ 'grep 'SomeString' $File' ]];then
   # Some Actions
 fi

我的代码有什么问题?


3
类似于https://dev59.com/eW445IYBdhLWcg3wq8FY的问题,我需要在Bash shell中测试一个字符串是否存在于文件中。 - Pawel
这是如何对“command”的输出执行grep命令的方法:https://dev59.com/62ct5IYBdhLWcg3wEJYm - rogerdpack
11个回答

724
if grep -q SomeString "$File"; then
  Some Actions # SomeString was found
fi

在这里你不需要使用 [[ ]]。直接运行命令即可。当你不需要显示找到的字符串时,添加 -q 选项。

grep 命令返回0或1的退出代码,具体取决于搜索结果。如果找到了某些内容,则返回0;否则返回1。

$ echo hello | grep hi ; echo $?
1
$ echo hello | grep he ; echo $?
hello
0
$ echo hello | grep -q he ; echo $?
0
你可以将命令作为 if 语句的条件。如果该命令在退出代码中返回0,则表示条件为真;否则为假。
$ if /bin/true; then echo that is true; fi
that is true
$ if /bin/false; then echo that is true; fi
$

正如你所看到的,你可以在这里直接运行程序。无需额外使用[][[]]


2
你可能想考虑使用 -Fxq 参数,例如 https://dev59.com/eW445IYBdhLWcg3wq8FY#4749368。 - Grzegorz Wierzowiecki
5
考虑使用参数-m 1以提高扫描性能。返回第一次出现的结果。 - AlikElzin-kilaka
1
如果SomeString包含正则表达式特殊字符(如.),则可能会得到意外的结果。最安全的方法是始终使用fgrep(或grep -F)(除非您真的需要正则表达式,在这种情况下,egrep(或grep -E)可能是最好的选择)。 - Walter Tross
1
这个 if 的例子是不正确的,因为它只检查退出代码是否为非0。如果发生任何错误,比如文件无法读取,退出代码也是非0的。所以你必须做类似于 ec=$? 这样的事情,并检查它是否为 0(找到),然后如果它是 1(未找到),然后再检查它是否为其他值(失败)。 - ddekany
2
如果你想要否定,使用 ! 和一个空格:if ! grep -q SomeString ... - Cameron Tacklind
显示剩余6条评论

107

如果您想检查文件是否包含特定字符串,可以按照以下步骤进行。


if ! grep -q SomeString "$File"; then
  Some Actions # SomeString was not found
fi

1
假设你有多个字符串在“输入文件”中需要测试。你能否将你的解决方案与cat(和xargs)结合起来?或者你需要一个for循环? - qräbnö
能否将变量中的行与文本文件中的行进行比较?有没有办法设置多行进行比较,而不是仅限于“SomeString”? - Bando
grep -v 也可以否定条件。 - Tom Harrison

49
除了其他答案告诉您如何做您想要的事情之外,我还尝试解释一下问题所在(这就是您想要的)。 在 Bash 中,if 后面要跟一个命令。如果该命令的退出码等于 0,则执行 then 部分,否则执行 else 部分(如果有的话)。如其他答案所述,您可以使用任何命令来实现此目的:if /bin/true; then ...; fi。 [[是专门用于某些测试的内置 bash 命令,例如文件存在性、变量比较等。类似地,[是一个外部命令(通常位于 /usr/bin/[),它执行大致相同的测试,但需要]作为最后一个参数,这就是为什么]必须在左侧补充空格的原因,而这在]]中不是这样。在这里,您不需要[[或[。 另一件事是引用方式。在 bash 中,只有一种情况下引号成对嵌套,即"$(command "argument")"。但在 grep 'SomeString' $File 中,您只有一个单词,因为 grep '是一个带引号的单元,它与 SomeString 连接,然后再次连接到' $File'。由于使用了单引号,变量$File甚至没有被替换为其值。正确的方法是grep 'SomeString' "$File"。

23

最短(正确)版本:

grep -q "something" file; [ $? -eq 0 ] && echo "yes" || echo "no"

可以写成以下形式

grep -q "something" file; test $? -eq 0 && echo "yes" || echo "no"

但在这种情况下您不需要显式测试它,所以可以使用相同的方法:

grep -q "something" file && echo "yes" || echo "no"

6
如果在文件中查找到 something,则输出 yes,否则输出 no。完全没有必要对 $? 进行任何更改。 - Charles Duffy

12
##To check for a particular  string in a file

cd PATH_TO_YOUR_DIRECTORY #Changing directory to your working directory
File=YOUR_FILENAME  
if grep -q STRING_YOU_ARE_CHECKING_FOR "$File"; ##note the space after the string you are searching for
then
echo "Hooray!!It's available"
else
echo "Oops!!Not available"
fi

2
改变目录通常不是一个好主意(并且在这里完全没有必要,只需将文件名与目标目录一起限定即可)。然后你所拥有的东西与被接受的答案完全相同,只是更少细节而已。 - Mat
谢谢你的建议,Mat。 - Nevin Raj Victor

11
grep -q [PATTERN] [FILE] && echo $?

如果找到了该模式,则退出状态为 0(真); 否则为空字符串。


10
if grep -q [string] [filename]
then
    [whatever action]
fi

Example

if grep -q 'my cat is in a tree' /tmp/cat.txt
then
    mkdir cat
fi

8

如果您想检查字符串是否与整行匹配并且它是一个固定的字符串,可以这样做:

grep -Fxq [String] [filePath]

例子

 searchString="Hello World"
 file="./test.log"
 if grep -Fxq "$searchString" $file
    then
            echo "String found in $file"
    else
            echo "String not found in $file"
 fi

来自 man 手册:

-F, --fixed-strings

          Interpret  PATTERN  as  a  list of fixed strings, separated by newlines, any of 

which is to be matched.
          (-F is specified by POSIX.)
-x, --line-regexp
          Select only those matches that exactly match the whole line.  (-x is specified by 

POSIX.)
-q, --quiet, --silent
          Quiet; do not write anything to standard output.  Exit immediately with zero 

status  if  any  match  is
          found,  even  if  an error was detected.  Also see the -s or --no-messages 

option.  (-q is specified by
          POSIX.)

它不起作用。例如,如果我正在寻找行'hello',并且有一行说'hello world',那么答案应该是'在文件中未找到hello',因为hello并不等于整行。 - Berni

2

试试这个:

if [[ $(grep "SomeString" $File) ]] ; then
   echo "Found"
else
   echo "Not Found"
fi

4
我有些犹豫地弃权不给这个投票点踩的,但是Stack Overflow不应该持续传播这种扭曲的逻辑。grep之所以返回一个退出状态,是有非常好的理由的;将输出捕获到一个字符串中可能会在缓冲区中存储大量文本,只是为了说明它不为空。 - tripleee
1
@tripleee 这种回答正是踩负面评价的设计初衷。 - jbg

-1

我完成了这个,看起来运行良好。

if grep $SearchTerm $FileToSearch; then
   echo "$SearchTerm found OK"
else
   echo "$SearchTerm not found"
fi

1
引用已经损坏,您可能希望避免看到grep的输出。[/questions/10067266/when-to-wrap-quotes-around-a-shell-variable] - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接