web-dev-qa-db-ja.com

bashの単一操作でgrepの出力と戻り値を取得する

私はbashスクリプトを書いています。あるコマンドとgrepを実行します。

pfiles $1 2> /dev/null | grep name # $1 Process Id

応答は次のようになります。

sockname: AF_INET6 ::ffff:10.10.50.28  port: 22
peername: AF_INET6 ::ffff:10.16.6.150  port: 12295

応答は、行なし、1行、または2行です。
grepが行を返さない場合(grep戻りコード1)、スクリプトを中止します。 1行を取得した場合、A()またはB() 1行を超える場合は呼び出します。出力が1〜2の場合、grepの戻りコードは0です。ライン。

grepには戻り値(0または1)と出力があります。
どうすれば両方をキャッチできますか?私が次のようなことをした場合:

OUTPUT=$(pfiles $1 2> /dev/null | grep peername)

次に、変数OUTPUTは出力(文字列)を持ちます。また、grep実行のブール値も必要です。

7
ilansch

使用できます

output=$(grep -c 'name' inputfile)

変数outputには、数値01、または2が含まれます。次に、ifステートメントを使用して、さまざまなことを実行できます。

11
pfnuesel

これはかなり簡単です:

_OUTPUT=$(pfiles "$1" 2> /dev/null | grep peername)
grep_return_code=$?
_

$(…)コマンド置換が変数に割り当てられている場合、_$?_は$(…)の最後のコマンドから戻りコードを取得します。そしてもちろん、_$?_を明示的に参照する必要はありません。あなたは次のようなことができます

if OUTPUT = $(pfiles "$ 1" 2>/dev/null | grep peername)
 then 
# スクリプトの残りの部分
︙
 fi

または

もし  OUTPUT = $(pfiles "$ 1" 2>/dev/null | grep peername)
 then 
 exit 
 fi 
# スクリプトの残りの部分

このアプローチは、コマンドのoutputとそのreturn code(別名終了ステータス)が相関しない状況で役立ちます。しかし、grepの場合、それらは高度に相関しています。出力を生成した場合、成功しました。出力を生成しなかった場合、失敗しました。では、なぜoutputをテストしないのですか?

OUTPUT = $(pfiles "$ 1" 2>/dev/null | grep peername)
 if ["$ OUTPUT"] 
 then 
# スクリプトの残りの部分
︙
 fi

または

OUTPUT = $(pfiles "$ 1" 2>/dev/null | grep peername)
 if [-z "$ OUTPUT"] 
そして
 exit 
 fi 
# スクリプトの残りの部分

追伸シェル変数の参照(たとえば、_"$1"_)は、特に理由がない限り、引用している必要があります。

1
Scott

grepの結果が必要な場合は、他の回答で概説されている-cフラグを使用できません。ただし、実行できるのは2回実行され、1回は-cフラグを使用して一致数を取得し、もう1つは-cフラグを使用せずに一致を表示します。ただし、入力ファイルのサイズによっては、これは非常に非効率的な場合があります。

あなたはこのようなことをすることができます:

inputの内容:

The first line is foo
I have a drink at the bar
The third line is foo again

scriptの内容:

#!/usr/bin/env bash

countMatches(){
    echo Searching for "${1}"
    result=$(grep "${1}" input)
    if [ $? -eq 1 ]; then
        echo No match found
        echo
        exit 1
    fi

    if [ $(echo "${result}" | wc -l) -eq 1 ]; then
        echo 1 match found:
        echo "${result}"
        echo
    else
        echo 2 matches found:
        echo "${result}"
        echo
    fi
}

countMatches foo
countMatches bar
countMatches baz

scriptを呼び出したときの出力は次のとおりです。

Searching for foo
2 matches found:
The first line is foo
The third line is foo again

Searching for bar
1 match found:
I have a drink at the bar

Searching for baz
No match found
1
pfnuesel

このコードを試してみてください、あなたが望むことをしています。

  1. grep出力をOUTPUT変数に入れます
  2. ブール値としてgrep終了ステータスは必要ないと思います。それは0または1であり、あなたの仕事には適していません。行数-0、1、2などが必要です。したがって、OUTPUT変数の行を数えて、この数を2番目の変数line_countに入れます。結果には2つの変数があります。 1つ目はgrep出力、2つ目は行数です。
  3. 次に、caseステートメントのline_countを確認し、必要なアクションを実行します。

使用法:./switching_by_grep_result.sh your_file.txt

#!/bin/bash

# your code
OUTPUT=$(pfiles $1 2> /dev/null | grep name) # $1 Process Id

# count lines in the OUTPUT variable by using 'grep -c'
line_count=$(echo -n "$OUTPUT" | grep -c '^')

# checks lines count in here and invokes needed script or exit.
# if 0 lines - exit
# if 1 lines - invoke A
# if any other number of lines - invoke B
case $line_count in  
    0) echo 'exit'
    ;;  
    1) echo 'A() script invoking here'
    ;;  
    *) echo 'B() script invoking here'
    ;;  
esac
0
MiniMax