回答:
grep -o
は一致を出力するだけで、行は無視します。wc
それらを数えることができます:
grep -o 'needle' file | wc -l
これは「針」または「多針」にも一致します。
単一の単語のみ:
grep -o '\bneedle\B' file | wc -l
# or:
grep -o '\<needle\>' file | wc -l
\b
と\B
は何ですか?
uniq
は、隣接する同一行のみを削除します。重複が常にすぐ隣接するかどうかがまだわからない場合は、sort
フィードする前にする必要がありuniq
ます。
あなたは(たまに他の場所で常にLinuxやCygwinの上、)GNU grepのを持っている場合は、次のことができますから、出力ラインを数えますgrep -o
:grep -o needle | wc -l
。
Perlを使用して、(修正された後でも)あなたよりもエレガントな方法をいくつか紹介します。
perl -lne 'END {print $c} map ++$c, /needle/g'
perl -lne 'END {print $c} $c += s/needle//g'
perl -lne 'END {print $c} ++$c while /needle/g'
POSIXツールのみを使用する場合、可能であれば1つのアプローチは、入力をgrepに渡す前に単一の一致を持つ行に分割することです。たとえば、単語全体を検索する場合、最初にすべての非単語文字を改行に変換します。
# equivalent to grep -ow 'needle' | wc -l
tr -c '[:alnum:]' '[\n*]' | grep -c '^needle$'
そうでない場合、この特定のテキスト処理を行う標準コマンドはないため、sed(マゾの場合)またはawkを使用する必要があります。
awk '{while (match($0, /set/)) {++c; $0=substr($0, RSTART+RLENGTH)}}
END {print c}'
sed -n -e 's/set/\n&\n/g' -e 's/^/\n/' -e 's/$/\n/' \
-e 's/\n[^\n]*\n/\n/g' -e 's/^\n//' -e 's/\n$//' \
-e '/./p' | wc -l
以下はsed
and を使用したより簡単なソリューションですgrep
。これは、文字列またはブックごとの正規表現でも機能しますが、アンカーパターンでいくつかのコーナーケースで失敗します(たとえば、^needle
またはの2つの出現を検出\bneedle
しますneedleneedle
)。
sed 's/needle/\n&\n/g' | grep -cx 'needle'
上記のsed置換では、以前\n
は改行を意味していたことに注意してください。これはパターン部分では標準ですが、代替テキストでは、移植性のために、バックスラッシュと改行を置き換えます\n
。
needle
フィールドセパレータとしてawkを使用する別のソリューション:
awk -F'^needle | needle | needle$' '{c+=NF-1}END{print c}'
needle
句読点が続くマッチしたい場合、フィールドセパレータをそれに応じて変更してください。
awk -F'^needle[ ,.?]|[ ,.?]needle[ ,.?]|[ ,.?]needle$' '{c+=NF-1}END{print c}'
または、クラス:[^[:alnum:]]
を使用して、すべての非アルファ文字を包含します。
この例では、ファイルごとの合計数ではなく、行ごとのオカレンス数のみを出力します。それがあなたが望むものであれば、このような何かがうまくいくかもしれません:
perl -nle '$c+=scalar(()=m/needle/g);END{print $c}'
grep
が指定されていることは知っていますが、使用している人にとってack
は、答えは単純ack -ch <pattern>
です。