2016-12-10 9 views
0

grep -c0を返すと、スクリプトが-1の終了コードで失敗するのはなぜですか?これは、set -o errexitが設定されている場合にのみ発生します。0カウントのgrep "-c"がステータスコード-1のプログラムを終了する理由

コピー/貼り付け
cat <<'EOT' > /tmp/foo.sh 
#!/usr/bin/env bash 

function bash_traceback() { 
    local lasterr="$?" 
    set +o xtrace 
    local code="-1" 
    local bash_command=${BASH_COMMAND} 
    echo "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]} ('$bash_command' exited with status $lasterr)" 
    if [ ${#FUNCNAME[@]} -gt 2 ]; then 
    # Print out the stack trace described by $function_stack 
    echo "Traceback of ${BASH_SOURCE[1]} (most recent call last):" 
    for ((i=0; i < ${#FUNCNAME[@]} - 1; i++)); do 
    local funcname="${FUNCNAME[$i]}" 
    [ "$i" -eq "0" ] && funcname=$bash_command 
    echo -e " $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]}\t$funcname" 
    done 
    fi 
    echo "Exiting with status ${code}" 
    exit "${code}" 
} 

test_redirecting_of_stdout_stderr() { 

    # Exit program when error found 
    set -o errexit 

    # Exit program when undefined variable is being used 
    set -o nounset 

    local up_count 
    up_count=$(ls | grep -c NOTHING_MATCHED) 
    echo "up_count: $up_count" 
} 

# provide an error handler whenever a command exits nonzero 
trap 'bash_traceback' ERR 

set -o errtrace 

test_redirecting_of_stdout_stderr 

EOT 

bash /tmp/foo.sh 

bashシェルの出力
debian:~/my-mediawiki-docker$ bash /tmp/foo.sh 
Error in /tmp/foo.sh:31 ('up_count=$(ls | grep -c NOTHING_MATCHED)' exited with status 255) 
Traceback of /tmp/foo.sh (most recent call last): 
    0: /tmp/foo.sh:31  up_count=$(ls | grep -c NOTHING_MATCHED) 
    1: /tmp/foo.sh:40  test_redirecting_of_stdout_stderr 
Exiting with status -1 
debian:~/my-mediawiki-docker$ 
+0

[BashFAQ#105](http://mywiki.wooledge.org/BashFAQ/105)へのchepnerのリンクをエコーし​​てみましょう。 –

+0

(例えば、 'print-f '%s:%s:%s:%sを使用した場合、 $ {BASH_SOURCE [$ i + 1]} "" "$ {BASH_LINENO [$ i]}" "" $ funcname "')を使用します。 –

答えて

2

grepレポート "失敗" には、一致する行を検索に失敗した場合。ここman grepです:

EXIT STATUS 
     The exit status is 0 if selected lines are found, and 1 if not found. 

あなたはerrexit時にスクリプトを終了させずに非ゼロで終了するコマンドを許可したい場合は、|| trueを使用:このオプションを設定

up_count=$(ls | grep -c NOTHING_MATCHED) || true 
+0

':'の同義語 'true'はこの使用法では慣用的です。したがって、同じ目的を果たす 'foo ||:'がよく見られるかもしれません。 –

1

は、任意の非ゼロの終了を想定していますコマンドからのステータスは致命的なエラーです。 grepの場合はそうではありません。これは、単にゼロ以外の終了ステータスを使用して、単に一致しないことを示します。これは、あなたが

if grep "$pattern" file.txt; then 
    echo "Found a match" 
else 
    echo "Found no match" 
fi 

errexit特に上記のようなif条件で使用されるコマンドの終了ステータスを無視するようなコードを書くことができますが、

up_count=$(ls | grep -c NOTHING_MATCHED) 

のような行が「許可」されているかどうかを知ることができませんゼロ以外の終了ステータスを持つようにします。回避策は、一般的には

# As an aside, see http://mywiki.wooledge.org/ParsingLs 
up_count=$(ls | grep -c NOTHING_MATCHED) || : 

でそのようなコマンドを保護することであるerrexitに依存するよりも、あなた自身のエラーチェックを行う方が良いです。詳細については、http://mywiki.wooledge.org/BashFAQ/105を参照してください。

関連する問題