我对 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
即使用户键入Three
和Title
,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”文件:
书名:作者
姓名 书名:作者姓名
书名:作者姓名
书籍:作者姓名
与测试用例book
和author
.
答案2
好吧,你仍然还没有说你想要从什么输入得到什么输出,所以我必须猜测。我想如果用户输入Title="Three Little Pigs"
and Author="Mary Jane"
,或者如果用户输入Title="Cinderella"
and Author="Paul Johnson"
(或文件中的任何其他行),您想做一件事(例如,输出“Found”),以及其他事情(例如,输出“Not Found”)如果用户输入还要别的吗
(例如,Title="Three
和Author="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,如果标题或作者姓名包含冒号,或者用户输入正则表达式中的任何特殊字符(例如,^
, $
, \
, *
, [
, ]
,.
,或有时(
, )
, {
, }
,?
和+
)。