Unix向Bash脚本添加grep选项

Unix向Bash脚本添加grep选项,bash,unix,grep,Bash,Unix,Grep,在我正在使用的bash脚本中,我需要添加一个grep选项,以便在命令行中接受,以便只从与模式匹配的文件中读取单词。系统会提示用户输入图书、作者、出版商和出版年份,列表以book1~author1~pub1~date1格式存储在一个文件books中,每一个设置在单独的行上。如果在命令行(bookinfo print)传递“print”,则文件“books”内容将放入book:book1(\n)中的book\u打印文件中 作者:author1等。格式。我试图做的是添加一个grep选项,这样当在命令行

在我正在使用的bash脚本中,我需要添加一个grep选项,以便在命令行中接受,以便只从与模式匹配的文件中读取单词。系统会提示用户输入图书、作者、出版商和出版年份,列表以book1~author1~pub1~date1格式存储在一个文件books中,每一个设置在单独的行上。如果在命令行(bookinfo print)传递“print”,则文件“books”内容将放入book:book1(\n)中的book\u打印文件中 作者:author1等。格式。我试图做的是添加一个grep选项,这样当在命令行中使用-f选项指定字符串时,只有“books”文件中包含该模式的行才会放入“book\u print”文件中。例如,如果命令为“bookinfo-f“author2”,则只有“books”中包含author2的行才会放入book\u打印文件中。(bookinfo是脚本的名称)

这是我到目前为止所拥有的。我开始使用-f选项代码,但不知道从这里可以走到哪里

#!/bin/bash
n=${1:-1}
#while getopts f name
#do
#       case $name in
#               f)dopt=1;;
#               *) echo "Invalid arg";;
#       esac
#done
if [[ $1 == "print" ]]
then
    printf "Booktitle: \t\t %s\n" `awk -F '~' '{print $1}' books` >> book_print
    printf "Author(s): \t\t %s\n" `awk -F '~' '{print $2}' books` >> book_print
    printf "Publisher: \t\t %s\n" `awk -F '~' '{print $3}' books`  >> book_print
    printf "Year of Publication: \t %s\n" `awk -F '~' '{print $4}' books` >> book_print
else
    for ((i = 1; i < n + 1; i++))
    do
        echo -n "Booktitle: " 
        read  b
        book=$b
        echo -n $book >> books
        echo -n "~" >> books
        echo -n "Author(s): "
        read a
        author=$a
        echo -n $author >> books
        echo -n "~" >> books
        echo -n "Publisher: "
        read  p
        publisher=$p
        echo -n $publisher >> books
        echo -n "~" >> books
        echo -n "Year of publication: "
        read y
        year=$y
        echo $year >> books
    done
fi

我的books文件包含A~B~C~D和E~F~G~H行。当我运行命令。/bookinfo-F“A”时,我看到的是整个books文件,而不仅仅是包含A的行。

看起来您的方向正确,以下是您需要的:

#!/bin/bash

while getopts "f:" opt;
do
  case $opt in
    f)
      echo "Found pattern: $OPTARG"
      ;;
    *)
      echo "Wrong arg"
      # Call the usage function here
  esac
done

您可能需要阅读本文以进一步了解getops的工作原理。

不是答案,而是快速重写以使代码更加紧凑:

print() {
    # doing this in a single awk command is much more efficient
    # the default search pattern is "non-empty line"
    awk -F '~' -v pattern="${1:-.}" '
        $0 ~ pattern {
            printf "Booktitle: \t\t %s\n", $1
            printf "Author(s): \t\t %s\n", $2
            printf "Publisher: \t\t %s\n", $3
            printf "Year of Publication: \t %s\n", $4
        }
    ' books >> book_print
}

populate() {
    while true; do
        # use read -p to incorporate the prompt, 
        # and just use one variable per item
        read -p "Booktitle (blank to quit): " book
        [[ -z "$book" ]] && break
        reap -p "Author(s): " author
        read -p "Publisher: " publisher
        read -p "Year of publication: " year
        # critically important to quote the variables here:
        printf "%s~%s~%s~%s\n" "$book" "$author" "$publisher" "$year"
    done >> books
}

# magic getopts here to set the search pattern, say in $search variable,
# and a flag to indicate print versus populate

if [[ "$do_search" -eq 1 ]]; then
    print "$search"
else
    populate
done

每当我使用getopts时(很多),我都会添加一个
-h
选项来记录有效选项的内容。@glennjackman是的,这是一个很好的实践,而不是问题中所问的内容。:)谢谢你的帮助,我更改了我的while循环并用更改编辑了OP。我的脚本仍然不能正常工作,我想这可能是我的grep命令的结果。@tfreiner如果您可以添加一些书籍文件的示例测试用例,以及对脚本的特定调用的预期输出,那么我可能可以提供更多帮助。我找到了答案。当我应该使用grep$2时,我正在使用grep$OPTARG。谢谢你的帮助!
print() {
    # doing this in a single awk command is much more efficient
    # the default search pattern is "non-empty line"
    awk -F '~' -v pattern="${1:-.}" '
        $0 ~ pattern {
            printf "Booktitle: \t\t %s\n", $1
            printf "Author(s): \t\t %s\n", $2
            printf "Publisher: \t\t %s\n", $3
            printf "Year of Publication: \t %s\n", $4
        }
    ' books >> book_print
}

populate() {
    while true; do
        # use read -p to incorporate the prompt, 
        # and just use one variable per item
        read -p "Booktitle (blank to quit): " book
        [[ -z "$book" ]] && break
        reap -p "Author(s): " author
        read -p "Publisher: " publisher
        read -p "Year of publication: " year
        # critically important to quote the variables here:
        printf "%s~%s~%s~%s\n" "$book" "$author" "$publisher" "$year"
    done >> books
}

# magic getopts here to set the search pattern, say in $search variable,
# and a flag to indicate print versus populate

if [[ "$do_search" -eq 1 ]]; then
    print "$search"
else
    populate
done