使用 grep 检查文本文件中的 2 个精确字符串

使用 grep 检查文本文件中的 2 个精确字符串

我对 shell 脚本完全陌生,我一直在阅读有关如何使用不同grep函数的教程。不幸的是,大多数教程通常讨论从文本文件中 grep 字符串的某种模式。

但是,我试图在文本文件中搜索两个确切的字符串。

例如,这是我的内容BookDB.txt

Three Little Pigs : Mary Jane
Cinderella : Paul Johnson

read我尝试使用该函数获取用户输入

echo Title :
read Title 

echo Author : 
read Author

接下来,我使用了grep从中获得帮助的命令关联获取字符串并检查它是否存在于BookDB.txt文件中,并将echo $?命令输出分配给变量以显示一些消息。

grep -w "$Title" BookDB.txt
check1=`echo $?`    

grep -w "$Author" BookDB.txt    
check2=`echo $?`

if [ "$check1" -eq 0 ] && [ "$check2" -eq 0 ]; then
    echo Found
else
    echo Not Found
fi

即使用户键入ThreeTitle,Mary命令仍然返回 0。每当它返回 0 时,它Author就会echo$?显示文本文件中不需要的信息。

答案1

当你这样做时:

check=`echo $?`

您正在使 shell 扩展$?以组成命令echo $?,然后将其输出分配给变量。如果您想保存命令的返回状态,请删除中间人并执行以下操作:

check=$?

但是,在您的情况下,您不需要保存退货状态。该语句本身if可以进行测试。&&

因此,如果您想查找包含两个字符串的文本文件,请执行以下操作:

if grep -qwF "$Author" "BookDB.txt" && grep -qwF "$Title" "BookDB.txt"; then
    echo Yes
fi

该选项-q是抑制grep的输出,并且-F不将模式解析为正则表达式。

但是,根据您的示例,您最有可能正在寻找的是包含标题后跟作者姓名的行。所以你可以尝试这个:

if grep -q "^\\s*$Title\\s*:\\s*$Author\\s*\$" "BookDB.txt"; then
    echo yes
fi

这将要求用户输入完整的标题和完整的作者姓名,并确保大小写正确。所以也许你想要一些更宽松的东西:

if grep -qi "$Title.*:.*$Author" "BookDB.txt"; then
    echo yes
fi

现在您不关心大小写,也不需要全名(John并且john两者都匹配JOHN CAVENDISH)。同样适用于标题。


以下MCVE

echo Title:
read Title
echo Author:
read Author
if grep -qi "$Title.*:.*$Author" "BookDB.txt"; then
    echo Found
fi

适用于以下“BookDB.txt”文件:

书名:作者
姓名 书名:作者姓名
书名:作者姓名
书籍:作者姓名

与测试用例bookauthor.

答案2

好吧,你仍然还没有说你想要从什么输入得到什么输出,所以我必须猜测。我想如果用户输入Title="Three Little Pigs"and Author="Mary Jane",或者如果用户输入Title="Cinderella"and Author="Paul Johnson" (或文件中的任何其他行),您想做一件事(例如,输出“Found”),以及其他事情(例如,输出“Not Found”)如果用户输入还要别的吗 (例如,Title="ThreeAuthor="Mary",或Title="Three Little Pigs"Author="Paul Johnson")。我建议你建立在phk 的回答并做

if grep "^\s*$Title\s*:\s*$Author\s*$" BookDB.txt > /dev/null
then
    echo "Found"
else
    echo "Not Found"
fi

或者你可以将第一行更改为

if grep -x "\s*$Title\s*:\s*$Author\s*" BookDB.txt > /dev/null

笔记:

  • ^代表行的开头。
  • $代表行尾。
  • 因此,代表^pattern$pattern 占据了整条线。
  • grep -x "pattern"也代表着pattern 占据了整条线。如果你读过使用 grep 精确匹配字符串更仔细地看,你会发现你已经混淆了-w-x
  • \s表示空格字符。  \s*表示零个或多个空格字符。
  • 总而言之:该模式意味着行首有零个或多个空格字符,后跟标题,后跟零个或多个空格、冒号、零个或多个空格、作者,以及零个或多个空格(一行中没有其他内容)。
  • 用于> /dev/null 防止匹配行出现在输出(即屏幕)上。作为朱斯蒂指出,您还可以使用-q(或--quiet--silent) 选项来执行此操作。

正如所指出的PHK,如果标题或作者姓名包含冒号,或者用户输入正则表达式中的任何特殊字符(例如,^, $, \, *, [, ],.,或有时(, ), {, },?+)。

相关内容