Si vous avez GNU grep (toujours sur Linux et Cygwin, parfois ailleurs), vous pouvez compter les lignes de sortie degrep -o : grep -o needle | wc -l.
Avec Perl, voici quelques manières que je trouve plus élégantes que la vôtre (même après que ce soit réglé ).
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'
Avec les seuls outils POSIX, une approche, si possible, consiste à scinder l’entrée en lignes avec une seule correspondance avant de la transmettre à grep. Par exemple, si vous recherchez des mots entiers, commencez par transformer chaque caractère non-mot en une nouvelle ligne.
# equivalent to grep -ow 'needle' | wc -l
tr -c '[:alnum:]' '[\n*]' | grep -c '^needle$'
Sinon, il n'y a pas de commande standard pour effectuer ce traitement de texte particulier, vous devez donc vous tourner vers sed (si vous êtes masochiste) ou 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
Voici une solution plus simple utilisant sedand grep, qui fonctionne pour les chaînes ou même les expressions rationnelles mais qui échoue dans certains cas avec des motifs ancrés (par exemple, elle trouve deux occurrences de ^needleou \bneedledans needleneedle).
sed 's/needle/\n&\n/g' | grep -cx 'needle'
Notez que dans les substitutions sed ci-dessus, je voulais \ndire une nouvelle ligne. Ceci est standard dans la partie motif, mais dans le texte de remplacement, remplacez la barre oblique inverse par une nouvelle barre oblique inversée \n.
grepest spécifié, mais pour quiconque utiliseack, la réponse est simpleack -ch <pattern>.