1

テキストファイルがあります。

テキストファイルの情報は

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

1 番目は書籍名、2 番目は著者名、3 番目は価格、4 番目は数量、5 番目は販売数量です。

現在、私はこの一連のコードを持っています

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.

: 区切り文字を , に変更できる場所はありますか? また、米である3列目に$を追加しますか?

助けてください..

4

3 に答える 3

2

に変更record=grep -c "${Title}:${Author}" BookDB.txtするrecord=$(grep -c "${Title}:${Author}" BookDB.txt)と、エラーが修正されます。record=$(cmd)コマンドの出力をcmd変数に代入することを意味しますrecord。それがないと、シェルは環境変数設定 (record=grep) が先頭に追加されrecord=grep -c ...たコマンドとして解釈します。-c

ところで、DB 形式は列指向のテキスト データで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,カンマ区切りなど) の変更が容易になり、プログラムがより堅牢になります (一致する文字列を最初の 2 つのフィールドに制限するなど)。完全一致ではなくあいまい一致のみが必要な場合は、in 条件に変更でき==ます~

于 2013-01-23T07:47:04.447 に答える
1

「unnamed command -c」エラーは、割り当ての右側の部分をバッククォートまたは「$()」で囲むことで回避できます。例:

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

また、このスニペットは -i がまったく問題ないことを示しています。ただし、両方の grep コマンドで同じフラグのリストを使用する必要があることに注意してください (2 番目のコマンドには -F がありません) - もちろん -q を除きます。

とにかく、grep を 2 回実行するのはおそらく最善の方法ではありません。どうでしょう...

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`を\\...扱うのは難しく、「サブシェルのレベル」に応じて、それらは次のように解釈されます...

例: (一度だけ 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行数であり、先行するスペースではありません)。

于 2013-01-23T12:00:56.847 に答える