如何使用Bash测试文件中是否存在字符串?


Answers:


655
grep -Fxq "$FILENAME" my_list.txt

如果找到名称,则退出状态为0(true),否则为1(false),因此:

if grep -Fxq "$FILENAME" my_list.txt
then
    # code if found
else
    # code if not found
fi

说明

以下是手册页grep的相关部分:

grep [options] PATTERN [FILE...]

-F--fixed-strings

        将PATTERN解释为由换行符分隔的固定字符串列表,其中任何一个都要匹配。

-x--line-regexp

        仅选择与整行完全匹配的那些匹配项。

-q--quiet--silent

        安静; 不要在标准输出中写任何东西。如果发现任何匹配项,即使检测到错误,也以零状态立即退出。另请参阅-s--no-messages选项。

错误处理

正如注释中正确指出的那样,以上方法默默地将错误情况视为已找到字符串。如果要以其他方式处理错误,则必须省略该-q选项,并根据退出状态检测错误:

通常,如果找到选定的行,则退出状态为0,否则为1。但是,如果发生错误,则退出状态为2,除非使用-qor --quiet或or --silent选项并且找到选定的行。但是请注意,这只是POSIX任务,为如程序grepcmp以及diff,在错误的情况下,退出状态大于1; 因此,出于可移植性考虑,建议使用针对此一般条件进行测试的逻辑,而不是与2严格相等。

要抑制来自的正常输出grep,可以将其重定向到/dev/null。请注意,标准错误仍然是无向的,因此任何grep可能打印的错误消息都将最终出现在控制台上,如您所愿。

为了处理这三种情况,我们可以使用一条case语句:

case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
  0)
    # code if found
    ;;
  1)
    # code if not found
    ;;
  *)
    # code if an error occurred
    ;;
esac

2
如果我从bash脚本执行此命令,如何将0或1捕获到变量中?
Toren

6
@Toren可以使用访问最近的退出状态$?。您还可以在if语句旁边使用grep命令(如更新的答案所示)。
肖恩

5
您可以使用,grep -Fqx "$FILENAME"而不必担心变量内容中的正则表达式字符,也不必在搜索字符串中使用它们。
暂停,直到另行通知。

4
给那些看这个答案的人一些注意事项:1)在bash中,0始终为true,而其他任何东西始终为false 2)如果希望整行完全匹配,请仅使用-x标志。如果您只想查找文件中是否存在您的字符串,请将其保留。如果要查找字符串是否确实存在,但不一定匹配整个行(即,作为一个整体),请使用-w。
Schmick

1
我不明白这-q / --silent是需要的吗?即使错误发生,它也会错误地说“一切都好”。如果我没错的话。在这种情况下,概念似乎有缺陷。
redanimalwar

90

关于以下解决方案:

grep -Fxq "$FILENAME" my_list.txt

如果您想知道(像我一样)-Fxq用简单的英语是什么意思:

  • F:影响PATTERN的解释方式(固定字符串而不是正则表达式)
  • x:匹配整行
  • q:嘘...最少印刷

从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.)

5
-F不会影响文件处理,它会影响PATTERN的解释方式。通常,PATTERN被解释为正则表达式,但使用-F时,它将被解释为固定字符串。
亚当S

41

我想到的三种方法:

1)对路径中的名称进行简短测试(我不确定这可能是您的情况)

ls -a "path" | grep "name"


2)对文件中的字符串进行简短测试

grep -R "string" "filepath"


3)使用正则表达式的更长的bash脚本:

#!/bin/bash

declare file="content.txt"
declare regex="\s+string\s+"

declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
    then
        echo "found"
    else
        echo "not found"
fi

exit

如果您必须使用循环来测试文件内容上的多个字符串(例如在任何cicle上更改正则表达式),则此方法应该更快


10
为什么$ file_contenet之前和之后都需要空格?
EminezArtus'2

加1作为快速解决方案,而更通用的解决方案
Wassadamo

19

更简单的方法:

if grep "$filename" my_list.txt > /dev/null
then
   ... found
else
   ... not found
fi

提示:/dev/null如果要获得命令的退出状态,请发送至,而不是输出。


1
或使用-q--quiet:) 相同的方式
rogerdpack '19

-q这里就最好的答案达成共识,并排在第四位。这个世界上没有正义。
tatsu

14

最简单的方法是:

isInFile=$(cat file.txt | grep -c "string")


if [ $isInFile -eq 0 ]; then
   #string not contained in file
else
   #string is in file at least once
fi

grep -c将返回该字符串在文件中出现多少次的计数。


5

如果我正确理解了您的问题,这应该做您所需要的。

  1. 您可以通过$ check变量指定要添加的目录
  2. 如果目录已在列表中,则输出为“目录已列出”
  3. 如果目录尚未在列表中,则将其附加到my_list.txt

一行check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt


您不需要测试grep的输出,您可以直接使用grep -q并调用grep,if就像Thomas在他的回答中所做的那样。此外,问题不包括在将目录添加到列表之前检查目录是否存在(毕竟它可能是已删除目录的列表)。
sorpigal 2011年

我删除了示例脚本,它没有对Thomas给出的答案添加任何内容。
lecodesportif 2011年

3

如果只想检查一行是否存在,则无需创建文件。例如,

if grep -xq "LINE_TO_BE_MATCHED" FILE_TO_LOOK_IN ; then
  # code for if it exists
else
  # code for if it does not exist
fi  

3

我的版本使用fgrep

  FOUND=`fgrep -c "FOUND" $VALIDATION_FILE`
  if [ $FOUND -eq 0 ]; then
    echo "Not able to find"
  else
    echo "able to find"     
  fi  

我没有看到-c选项fgrep --help
南摹VU


1

@Thomas的解决方案由于某些原因对我不起作用,但是我的字符串较长,带有特殊字符和空格,因此我只更改了以下参数:

if grep -Fxq 'string you want to find' "/path/to/file"; then
    echo "Found"
else
    echo "Not found"
fi

希望对别人有帮助



0
grep -Fxq "String to be found" | ls -a
  • grep将帮助您检查内容
  • ls将列出所有文件

@ThomWiggers我尝试了同样的方法,并且对我有用。
Shinoy Shaji

-1
if grep -q "$Filename$" my_list.txt
   then
     echo "exist"
else 
     echo "not exist"
fi
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.