1つのコマンドラインステートメントにGrepの2つの異なる要件があります。

1つのコマンドラインステートメントにGrepの2つの異なる要件があります。

この文字列を含む最後の3行を印刷する方法と、#includeこのtester.c文字列を含む行が3行未満の場合に印刷します。フルファイル

これまで私は以下を持っています:

grep "#include" tester.c | tail -3

しかし、要件の後半をどのように含めるべきかわかりません。これは宿題であり、答えは一行でなければなりませんが、いいえ、;とてもわかりません。

答え1

tail -33行以上を印刷せずに3行以下で印刷します。したがって、「grep」が3つ以下の一致する行を見つけると、tailはそれらをすべて標準出力に渡します。一致するものが3つ以上の場合は、tail3行だけに制限してください。

あなたのコマンドが正確に必要なので、ここに投稿する前に問題を解決しました。

夜に働くと、これが起こります:)

編集:あなたの質問を誤って読んだ可能性があります。

一致するファイルが3つ未満の場合にファイル全体を印刷するには、次の手順を実行します。

f="testfile.c" && C=3 && [ $(grep -c "#include" ${f}) -lt ${C} ] && cat ${f} || grep "#include" ${f} |tail -${C}

ただし、潜在的に遅いFS(NFSなど)を処理したり、行が多いファイルや非常に長い行があるファイルを処理したりする場合は、読みすぎる必要があるため、遅すぎる可能性があります。ファイルをダブル。

f="testfile.c" && C=3 && CONTENT=$(cat "${f}") && MATCHES=$(echo "$CONTENT"|grep "#include"|tail -${C}) && [ $(echo "$MATCHES" | wc -l) -lt ${C} ] && echo "$CONTENT" || echo "$MATCHES"

これにより、ファイルを一度だけ開いて読み取ることができますが、RAM(ストレージデバイスよりはるかに高速です)にバッファリングされます。 RAMが不足しているかファイルをバッファリングするのにコストがかかりすぎる場合は、[ファイルを2回開く]最初のコマンドを使用すると速度が遅くなりますが、OSやアプリケーションは中断されません。 「D」状態に閉じ込められている場合が高くなります... OSにも良くありません...)

答え2

次のように ";"なしでSildorethが言ったようにすることができます。

test $(echo `grep "#include" tester.c` | wc -l) -ge 3 && {echo `grep "#include" tester.c` | head -n 3} || cat tester.c

答え3

特に、元の投稿から要求されたコマンドが正確に必要なコマンドであることを考慮すると、これは奇妙な質問です。

たとえば、file.cにはgrep式に一致する15行があります。

% grep -c "#include" file.c 15 % grep "#include" file.c | head -18 #(more than the number of matches) #include <sys/blah.h> #include <sys/blah2.h> #include <sys/blah3.h> #include <sys/blah4.h> #include <sys/blah5.h> #include <sys/blah6.h> #include <sys/blah7.h> #include <sys/blah8.h> #include <sys/blah9.h> #include <sys/blah10.h> #include <sys/blah11.h> #include <sys/blah12.h> #include <sys/blah13.h> #include <sys/blah14.h> #include <sys/blah15.h>

または

% grep "#include" file.c | tail -18 #include <sys/blah.h> #include <sys/blah2.h> #include <sys/blah3.h> #include <sys/blah4.h> #include <sys/blah5.h> #include <sys/blah6.h> #include <sys/blah7.h> #include <sys/blah8.h> #include <sys/blah9.h> #include <sys/blah10.h> #include <sys/blah11.h> #include <sys/blah12.h> #include <sys/blah13.h> #include <sys/blah14.h> #include <sys/blah15.h>

これがあなたの業務パラメータに合わない理由を説明してください。

答え4

この試み:

lines=$(grep "#include" tester.c);
   test $(echo $lines | wc -l) -ge 3 && {echo $lines | head -n 3} || cat tester.c;
       unset lines

注:このソリューションは1行に入力できます。読みやすいように複数行に分けました。

編集する

コメントに応じてセミコロンを&&次のように変更できると思います。

lines=$(grep "#include" tester.c) &&
   test $(echo $lines | wc -l) -ge 3 && {echo $lines | head -n 3} || cat tester.c

技術的に問題はありませんがlines解決されました。これも&&不要ですが大丈夫です。

この修正されたソリューションは、他のソリューションと同じようにファイルを2回読み取る必要がないという利点があります。

それができない場合は、test次のように括弧を使用できます。

lines=$(grep "#include" tester.c) &&
   [ $(echo $lines | wc -l) -ge 3 ] && {echo $lines | head -n 3} || cat tester.c

中かっこを削除することもできます。

lines=$(grep "#include" tester.c) &&
   [ $(echo $lines | wc -l) -ge 3 ] && echo $lines | head -n 3 || cat tester.c

これらのバリエーションの1つが要件を満たす必要があります。

関連情報