2017-03-24 21 views
0

私は次のリストがあります検索見つかった場合(BASH)

COX1 
    COX1 
    COX1 
    COX1 
    COX1 
    Cu-oxidase 
    Cu-oxidase_3 
    Cu-oxidase_3 
    Fer4_NifH 

を、私はCOX1Cu-oxidaseがリストにある場合は、検索したい、私はCu-oxidase_3場合、xyzを印刷したいとFer4_NifHは、最初の2つがリストにある場合、それはabcを独立して印刷する必要があります(あまりにもリストに含まれている

これは私がこれまでのスクリプトができるもの:。

if grep 'COX1' file.txt; then echo xyz; else exit 0; fi

ですが、もちろん不完全です。 これに対する解決策はありますか?

理想的に私の出力は次のようになります。

xyz 
abc 
+1

どこにいらっしゃるのですか?あなたはgrepの使い方を知っていて、 'if'を使う方法を知っていますが、他に何を知りたいですか?あなたがそれ以上何もしようとしていないので、不完全なように見えます。 – grail

+0

私は 'COX1&Cu-oxidase'または' Cu-oxidase_3&Fer4_NifH' PLUSのコマンドを追加して別の文字列を出力しています。 – rororo

+0

bashでは&&を使用してテストの中に入れられます(少なくとも、最初のコマンドが返された場合と同様に動作します)。また、grepで-qを使用することをお勧めしますので、各grepの出力から追加のノイズを得ることはありません。 – grail

答えて

-1

上記は、これを達成するために非常に冗長な方法です。そこ少ないif Sと同じと少ないgrep秒を書くための方法がありますが、私は本当にあなたのロジックを見せたかった:

あなたはgrepコマンドを実行し、$?とその戻り値をチェックし、最終的に条件に作用します。

# default values 
HAS_COX1=0 
HAS_CUOX=0 
HAS_CUO3=0 
HAS_FER4=0 

# run silently grep 
grep -q 'COX1' file.txt 
# check for return value and set variable accordingly 
if [ $? -eq 0 ]; then HAS_COX1=1; fi 

# same as above 
grep -q 'Cu-oxidase' file.txt 
if [ $? -eq 0 ]; then HAS_CUOX=1; fi 
grep -q 'Cu-oxidase_3' file.txt 
if [ $? -eq 0 ]; then HAS_CUO3=1; fi 
grep -q 'Fer4_NifH' file.txt 
if [ $? -eq 0 ]; then HAS_FER4=1; fi 

if [ $HAS_COX1 -eq 1 ]; then 
    if [ $HAS_CUOX -eq 1 ]; then 
    echo 'xyz' 
    exit 0 
    fi 
fi 

if [ $HAS_CUO3 -eq 1 ]; then 
    if [ $HAS_FER4 -eq 1 ]; then 
    echo 'abc' 
    exit 0 
    fi 
fi 

echo 'None of the checks where matched' 
exit 1 

用心:をこのコードはテストされていないので、

☺コードのバグがあるかもしれません両方の条件が満たされたとき、それは'xyz''abc'の両方を印刷することはできません(それと同じように、完璧ではありません私が提供する構文で簡単に修正することができます)。また$HAS_CUOX$HAS_CUO3が見つかるたびに1に設定されます(grep正規表現では境界チェックなし)。

grepの正規表現として'COX1\|Cu_oxidase'のようなものを使用してチェックするために、条件のセットごとに1つのgrepを使用して、さらにコードを実行することができます。また、上記のマイナーな問題を修正してください。


理想的に私の出力は次のようになります。 xyz abc

私は上記のスクリプトを書いた後、あなたはあなたの予想される出力を追加しましたが、私はあなたを与えた要素を与え、あなたのことができるようになりどのように改善するかを理解する(基本的には、私が配置したexit 0を削除し、出力がない場合はexit 1を実行する)

または汚れた溶液としてすべてexitを取り除くだけです。

+1

これには構文エラーといくつかの厄介な(しかし無害な)反パターンがあります。 – tripleee

+1

grepはstdoutを避けるために '-q'オプションを持っているだけでなく、if grep -q 'search'ファイル 'として使用されます – Sundeep

+0

コンテキスト上の注釈のために、私はSOアプリケーションで私の電話でスクリプトを書いたそれを書いている間にシェルにアクセスすることはできません。そして、ありがとう、@ sundeep、私はいつも '-q'について忘れてしまいます。私はそれを修正します。 @トライプレイ私は本当にアンチパターンに関するあなたの見解に同意しない、このバージョンで私の取ることは、それを読みやすくすることでした。 – zmo

0

Awkを使用すると、複数の正規表現を簡単に検索し、一致した文字列以外のものを簡単に印刷できます。 (grepは複数のパターンも簡単に検索できますが、任意の文字列ではなく、一致またはその行番号またはファイル名を出力します)。

以下は、1行に1つのトークンがあることを前提としています。この仮定はスクリプトを本当にシンプルにしますが、他のシナリオをサポートすることも難しくありません。それは、ファイル内のすべての行を読み取ったときは、各トークン(各ライン上の実際最初の空白で区切られたトークン)の連想配列を構築した後、端部で

awk '{ a[$1]++ } 
    END { if (("COX1" in a) && ("Cu-oxidase" in a)) print "xyz"; 
     if (("Cu-oxidase_3" in a) && ("Fer4_NifH" in a)) print "abc" }' file.txt 

、求めトークンとして存在するか否かをチェック配列内のキー。

大きな入力ファイルと多数のパターンがある場合は、入力ファイルを1回だけ通過させるのが大きなメリットです。完全性のために、grepで複数のパスを実行する構文は非常に簡単です。さらに

grep -qx 'COX1' file.txt && grep -qx 'Cu-oxidase' file.txt && echo xyz 

Noticeを一致させるために全体の線を必要とする-xスイッチ('Cu-oxidase'のCu-oxidase_3行に一致し、さもなければ、正規表現)を省略でき

if grep -qx 'COX1' file.txt && grep -qx 'Cu-oxidase' file.txt 
then 
    echo xyz 
fi 

+0

まあ、反パターンについて... awkは独自の反パターンです – zmo

+0

説明してください?シェルだけでは処理できないものがたくさんあります。標準のサポートツールを使用することを学ぶことは、シェルスクリプトを書くことを学ぶ上で重要なステップです。 – tripleee

+0

まず最初に、私はユーモアを作っていました(それゆえに、スマイリー絵文字) - 私の*** OPINION ***は、awkは非常に独自の奇妙な構文を持っています、そして、通常、高度なawkが必要になると、ステップアップして適切な動的言語を使用します。 * N.B:私は意見の部分に重点を置いています。私はあなたが同意しないと思います。私はそれを尊重します。私は炎を上げようとはしていません☺* – zmo

関連する問題