grep -c
は、ファイル内で文字列が出現する回数を見つけるのに役立ちますが、1行に1回しか出現しません。行ごとに複数の出現を数える方法は?
私はよりエレガントなものを探しています:
Perl -e '$_ = <>; print scalar ( () = m/needle/g ), "\n"'
grepの-o
は、行を無視して、一致のみを出力します。 wc
はそれらを数えることができます:
grep -o 'needle' file | wc -l
これは「針」または「複数針」にも一致します。
単一の単語のみを照合するには、次のいずれかのコマンドを使用します。
grep -ow 'needle' file | wc -l
grep -o '\bneedle\b' file | wc -l
grep -o '\<needle\>' file | wc -l
GNU grep(常にLinuxおよびCygwinで、場合によっては他の場所でも)がある場合) grep -o
からの出力行をカウントする :grep -o needle | wc -l
。
Perlを使って、私があなたよりもエレガントだと思う方法がいくつかあります(たとえ fixed になった後でも)。
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に渡す前に、単一の一致で入力を行に分割することです。たとえば、単語全体を検索する場合は、最初にWord以外のすべての文字を改行にします。
# 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
とgrep
を使用したより簡単な解決策です。これは文字列または書籍別の正規表現でも機能しますが、アンカーパターンでいくつかのコーナーケースで失敗します(たとえば、^needle
の2つの出現を検出します)またはneedleneedle
内の\bneedle
)。
sed 's/needle/\n&\n/g' | grep -cx 'needle'
上記のsed置換では、\n
を使用して改行を意味していることに注意してください。これはパターン部分では標準ですが、移植性のために、\n
をバックスラッシュ-改行に置き換えてください。
もし私と同じように "両方;それぞれ正確に1つ"、 (これは実際には「どちらかです; 2回」)それからそれは簡単です:
grep -E "thing1|thing2" -c
そして、出力を確認します2
。
このアプローチの利点(正確に1回の場合is必要なもの)は、簡単にスケーリングできることです。
Awkとneedle
をフィールド区切り記号として使用する別のソリューション:
awk -F'^needle | needle | needle$' '{c+=NF-1}END{print c}'
needle
に続けて句読点を付ける場合は、それに応じてフィールド区切り文字を変更します。
awk -F'^needle[ ,.?]|[ ,.?]needle[ ,.?]|[ ,.?]needle$' '{c+=NF-1}END{print c}'
またはクラスを使用します:[^[:alnum:]]
は、すべての非英字を含みます。
これは私の純粋なbashソリューションです
#!/bin/bash
B=$(for i in $(cat /tmp/a | sort -u); do
echo "$(grep $i /tmp/a | wc -l) $i"
done)
echo "$B" | sort --reverse
この例では、ファイル内の合計ではなく、行ごとの発生数のみを出力します。それがあなたの望むことなら、このようなものがうまくいくかもしれません:
Perl -nle '$c+=scalar(()=m/needle/g);END{print $c}'