2017-08-07 10 views
0

は、これは私が、私はそれを修正する方法を知っている実際のところbashの単項演算子が予想誤差

#!/bin/bash 

expression=$1 
field=$2 
if [ -z "$expression" ]; then 
echo "expression is missing" 
exit 1 
fi 

if [ -f /home/miked/table ]; then 
    if [ -f table ] && [ grep "$expression table" ]; then 
    grep "$expression" table | cut -d: -f${2:-3} | clipit 
    else 
    echo "no match found" 
    fi 
else 
    echo "there is no table file" 
fi 

を思い付いたスクリプトですが、それは固定だ理由 私は知りません。

grep"の間のスペースを削除すると、すべて正常に動作していますが、私はその理由を理解できないようです。

コマンドラインに直接grep something fileを入力すると、正常に動作しています。スクリプト内でgrep"に貼り付けるのはなぜですか?

+0

? – TallChuck

+0

はい、私はここで説明が必要です – jaindoe

+0

サイドノートは質問にはあまり関係ありません:なぜ '/ home/miked/table'が存在するのかまずチェックしますが、現在のディレクトリで' table'を使って作業していますか? –

答えて

2

角かっこ。 [testコマンドのエイリアスです(一般に、ほとんどのシェルは組み込み関数を使用してそれを複製します)。 man testを使用して、そのコマンドの構文を見ることができます。

#!/bin/bash 

expression="$1" 
field="$2" 
if [ -z "$expression" ]; then 
    echo "expression is missing" 
    exit 1 
fi 

if [ -f /home/miked/table ]; then 
    if [ -f table ] && grep "$expression table"; then 
    grep "$expression" table | cut -d: -f${2:-3} | clipit 
    else 
    echo "no match found" 
    fi 
else 
    echo "there is no table file" 
fi 

しかし、あなたのスクリプトで多くの問題がある:何が欲しいのは$expression tableは、いくつかのファイルに存在し、その代わりに、あなたのようにそれを記述する必要があるかどうかを確認することです。

  1. あなたは代わりにあなたはそのために別の関数を使用し、理想的に、echo "error" >&2を使用する必要があり、他のツールにスクリプトの出力をパイプときにそれらが見えなくなりますstdout代わりのstderrにエラーを出力します。
  2. grepには1つの引数しか渡されず、2:grep "$expression" tableとする必要があります。
  3. あなたの最初のgrepコールはstdoutにも印刷されますので、それを上回りたいと思うので、代わりに-qフラグを使用してください。
  4. set -eを使用して「エラーで終了」を有効にして、あなたは外のファイルを使用していないので、あなたはちょうどそれのチェックを削除することができset -o pipefail
  5. を使用して「パイプエラーで終了」することをお勧めします。
  6. $field変数は使用しないでください。
  7. ifの代わりにガード句を使用して、致命的なエラーチェックを行うと、スクリプトを簡単にリファクタリングできるようになります。

ので、ファイル全体をのように書くことができます:あなたがしなければ、それは[グレップの$式テーブル\ `` \] `動作しない`

#!/bin/bash 

set -eo pipefail 

perror() { 
    echo "$1" >&2 && exit 1 
} 

expression=$1 
field=${2:-3} 
file=${3:table} 

[ -z "$expression" ] || perror "expression is missing" 
[ -f "$file" ] || perror "there is no '$file' file" 

grep "$expression" "$file" | cut -d: -f"${field}" | clipit || perror "no match found" 
+0

最初の例の 'grep" $ expression table "はうまくいきません、grepは2つの引数を必要とします。あなたはこれを後で指摘します。 –

+0

@ベンジャミンW。最初のスクリプトは著者エラーのために修正されています。 2番目の部分はこのスクリプトの他のすべての問題です。その問題も言及されています(OPの意図が何であるかを100%確信することはできません)。 – Hauleth

+1

十分に公正。 'set -e'には多くの落とし穴が付いてくることに注意してください。http://mywiki.wooledge.org/BashFAQ/105 –

0

[ ]はまったく必要ありません。あなたはgrepの終了ステータスに関心があります。すでにgrepを終了しています。

if [ -f table ] && grep -q "$expression" table; then 

ファイル名はどちらか、引用符であってはならない。その出力を抑制するために、あなたは-qオプションを使用することができます。

[ ]をテストせずに使用すると、デフォルトで-n: "文字列が空でない場合はtrue"になります。このテストでは引数が1つしかないので、空白を削除するとうまくいくように見えます。つまり、文字列grep$expression tableが展開されるかどうかがチェックされ、常にゼロでないかどうかがチェックされます。あなたは再びそれをやっているので、「表」が存在する場合は、すでにテストしてみた if [ -f table ] && [ grep "$expression table" ]; then

:この問題を解決するために行うことができるかなりの数のものがあります

+0

grep "expression table"の結果が2つの引数になるのはなぜですか?私はそれがgrepの終了ステータスが0であると思っていましたが、もしそれ以外の場合は、この行が2つの引数を生成する理由は、1の終了ステータスをもたらすことはありませんか? – jaindoe

+0

これは '[]'の2つの引数です:最初は 'grep'、2番目は' '$ expression table" 'です。 –

0

は、あなたの主な問題は次の行ですそれが成功すると、式[ grep "$expression table" ]が評価されています。これは、'[' grep 'expression table' ']'に分類され、本質的に何も意味しません。

代わりに、$()を使用して出現回数を評価するか、ベンジャミンの言い回しのように、必要な場合はスキップしてください。

私たちはまだテストを使用しているか何か

#!/bin/bash 
expression=$1 
field=$2 
table_file=/home/miked/table 
if [ -z "$expression" ]; then 
    echo "expression is missing" 
    exit 1 
fi 

if [ -f $table_file ]; then 
    if [ $(grep -q "$expression $table_file") -gt 0 ]; then 
     grep "$expression" $table_file | cut -d: -f${2:-3} | clipit 
    else 
     echo "no match found" 
    fi 
else 
    echo "there is no table file" 
fi 

このようなお知らせをお勧めします、これはに凝縮することができます:あなたは、正方形の内側 grep呼び出しをラップする必要はありません

#!/bin/bash 
expression=$1 
field=$2 
table_file=/home/miked/table 
if [ -z "$expression" ]; then 
    echo "expression is missing" 
    exit 1 
fi 

if [ -f $table_file ]; then 
    grep -q $expression $table_file && grep "$expression" $table_file | cut -d: -f${2:-3} | clipit || echo "no match found" 
else 
    echo "there is no table file" 
fi 
+0

これは本当に 'grep -q'の主な使用例です。 –

+0

あなたはそうです、私はそれを見過ごしてしまいました –