1

我有一个文本文件。

文本文件中的信息是

Book1:Author1:10.50:50:5
Book2:Author2:4.50:30:10

第一个是书名,第二个是作者名,第三个是价格,第四个是数量,第五个是销量。

目前我有这组代码

function search_book
{
    read -p $'Title: ' Title
    read -p $'Author: ' Author
    if grep -Fq "${Title}:${Author}" BookDB.txt
    then
        record=grep -c "${Title}:${Author}" BookDB.txt
        echo "Found '" $record "' record(s)"
    else
        echo "Book not found"
    fi
}

对于 $record,我正在尝试计算找到的行数。我是否为它做了正确的事情,因为当我运行此代码时,它只显示错误命令 -c。

当我这样做时

echo "Found"
grep -c "${Title}" BookDB.txt
echo "record(s)"

它有效,但输出是

Found
1
record(s)

我希望他们在一起

我是否也可以将 grep -i 添加到 grep -Fq 以便将所有内容变成小写字母以便更好地搜索?

假设我要搜索 Book1 和 Author1,如果我输入“ok”作为标题,输入“uth”作为作者,是否有任何 % 命令添加到标题以在标题和作者中间进行搜索?

预期的输出也预计是..

Found 1 record(s)

Book1,Author1,$10.50,50,5.

有什么地方可以将 : 分隔符更改为 , 吗?还要在第三列加$是大米?

请帮忙..

4

3 回答 3

2

更改record=grep -c "${Title}:${Author}" BookDB.txtrecord=$(grep -c "${Title}:${Author}" BookDB.txt)将修复错误。record=$(cmd)意味着将命令的输出分配给cmd变量record。没有它,shell 将解释为由环境变量设置 (record=grep) 前置record=grep -c ...的命令。-c

顺便说一句,由于您的数据库格式是面向列的文本数据,awk因此应该是一个更好的工具。示例代码:

function search_book
{
    read -p $'Title: ' Title
    read -p $'Author: ' Author
    awk -F: '{if ($1 == "'"$Title"'" && $2 ~ "'"$Author"'") {count+=1; output=output "\n" $0} } 
    END {
        if (count > 0) {print "found", count, "record(s)\n", output}
        else {print "Book not found";}}'  BookDB.txt
}

如您所见,使用 awk 可以更轻松地更改分隔符(例如awk -F,,用于逗号分隔符),并且还使程序更加健壮(例如,它将匹配字符串限制为前两个字段)。如果您只需要模糊匹配而不是精确匹配,则可以更改==~条件。

于 2013-01-23T07:47:04.447 回答
1

“未命名的命令 -c”错误可以通过将赋值的右侧部分括在反引号或“$()”中来避免,例如:

record=`grep -ic "${Title}:${Author}" BookDB.txt`
record=$(grep -ic "${Title}:${Author}" BookDB.txt)

此外,此片段显示 -i 非常好。但是,请注意,两个 grep 命令应该使用相同的标志列表(第二个中缺少 -F) - 当然,-q 除外。

无论如何,执行两次 grep 可能不是最好的方法。关于什么...

record=`grep -ic "${Title}:${Author}" BookDB.txt 2>/dev/null`
if [ ! -z "$record" ]; then ...

... 或类似的东西?

顺便说一句:如果省略 -F,则允许用户使用正则表达式进行操作。这不仅会提供通配符,还会提供更复杂模式的可能性。您还可以对脚本应用一个选项来决定是否使用 -F ..

最后但同样重要的是:要修改行,以更改分隔符或操作列,您至少可以查看手册页或 awk(1) 或 cut(1)。虽然我认为这里更适合使用更复杂的语言,例如 perl(1) 或 python(1),尤其是当脚本要扩展更多功能时。

于 2013-01-23T07:55:11.737 回答
0

添加到上面的答案(这开始是评论,但它增长了......):

这种$()形式是首选: - 它允许嵌套, - 它简化了很多的使用"and '(可以说,嵌套的每个“级别”都在它们的级别上看到它们)。很难处理as using nested quotes and single-quotes becomes a nightmare of` 并且\\...取决于“子shell的级别”,它们将被解释为......

例如:(尝试只 grep 一次)

export results="$(grep -i "${Title}:${Author}" BookDB.txt)" ; 
export nbresults=$(echo "${results}" | wc -l) ; 
printf "Found %8s record(s)\n" "nbresults" ; 
echo "$nbresults" ;  

或者,如果太多结果无法放入变量中:

export tmpresults="/tmp/results.$$"
grep -i "${Title}:${Author}" BookDB.txt > "${tmpresults}" 
export nbresults=$(wc -l "${tmpresults}") ; 
printf "Found %8s record(s)\n" "nbresults" ; 
cat "${tmpresults}" ; 
rm -f "${tmpresults}" ;

注意:我使用"了很多(除了wc -l一行)来说明有时可能需要它(不是在上述所有情况下!)来保留空格、换行符等(我故意将它用于 nbresults,以便它只包含行数,而不是前面的空格)。

于 2013-01-23T12:00:56.847 回答