Compter les occurrences d'un caractère dans une chaîne à l'aide de Bash


123

J'ai besoin de compter le nombre d'occurrences d'un caractère dans une chaîne en utilisant Bash.

Dans l'exemple suivant, lorsque le caractère est (par exemple) t, il echoest le nombre exact d'occurrences tdans var, mais quand le caractère est une virgule ou point - virgule, il affiche zéro:

var = "text,text,text,text" 
num = `expr match $var [,]`
echo "$num"

Réponses:


118

J'utiliserais la awkcommande suivante :

string="text,text,text,text"
char=","
awk -F"${char}" '{print NF-1}' <<< "${string}"

Je divise la chaîne par $charet j'imprime le nombre de champs résultants moins 1.

Si votre shell ne prend pas en charge l' <<<opérateur, utilisez echo:

echo "${string}" | awk -F"${char}" '{print NF-1}'

5
@HattrickNZ Ensuite, utilisez:$(grep -o "$needle" < filename | wc -l)
hek2mgl

13
@Amir À quoi vous attendez-vous?
hek2mgl

3
Vous pouvez sauter le wc -l, utilisez simplement grep -c, il fonctionne à la fois sur bsd grep et linux grep.
andsens

8
@andsens grep -caffichera uniquement le nombre de lignes correspondantes. Il ne compte pas plusieurs correspondances par ligne.
hek2mgl

1
Je veux compter les '$' dans une chaîne, comment puis-je échapper '$' à la chaîne principale?
masT

118

vous pouvez par exemple supprimer tous les autres caractères et compter ce qui reste, comme:

var="text,text,text,text"
res="${var//[^,]}"
echo "$res"
echo "${#res}"

va imprimer

,,,
3

ou

tr -dc ',' <<<"$var" | awk '{ print length; }'

ou

tr -dc ',' <<<"$var" | wc -c    #works, but i don't like wc.. ;)

ou

awk -F, '{print NF-1}' <<<"$var"

ou

grep -o ',' <<<"$var" | grep -c .

ou

perl -nle 'print s/,//g' <<<"$var"

1
un autre truc ici commey="${x//[^s|S]}"; echo "${#y}"
Aquarius Power

4
utilisez le premier, vous devez toujours éviter de recourir à un autre processus pour effectuer un travail comme celui-ci, cela peut avoir un impact important sur les performances lors de l'utilisation avec de grandes boucles d'itération. En règle générale, l'exécution d'un processus externe doit être le dernier recours lors de l'utilisation d'opérations itératives ou répétées.
osirisgothra

Pourquoi tu n'aimes pas wc? Il joue au golf!
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 六四 事件 法轮功 包 卓 轩 parce que par exempleecho -n some line | wc -l
jm666

Le bloc de code 4 est le meilleur à mon avis. Nous devons faciliter l'accès à:tr -dc ',' <<<"$var" | wc -c
bgStack15

68

Vous pouvez le faire en combinant tret des wccommandes. Par exemple, pour compter edans la chaîne referee

echo "referee" | tr -cd 'e' | wc -c

production

4

Explications: La commande tr -cd 'e'supprime tous les caractères autres que «e» et la commande wc -ccompte les caractères restants.

Plusieurs lignes d'entrée sont également bonnes pour cette solution, comme la commande cat mytext.txt | tr -cd 'e' | wc -cpeut compter edans le fichier mytext.txt, même si le fichier peut contenir plusieurs lignes.


3
Votre solution semble être la plus propre et la plus facile à retenir, merci!
jirislav

C'est bien. Je vous remercie!
Kodie Grantham

J'adore ça, parce que je déteste awk!
franzisk

3

S'appuyant sur les bonnes réponses et commentaires de chacun, c'est la version la plus courte et la plus douce:

grep -o "$needle" <<< "$haystack" | wc -l


2

awk fonctionne bien si votre serveur l'a

var="text,text,text,text" 
num=$(echo "${var}" | awk -F, '{print NF-1}')
echo "${num}"

Juste une note: awk -F,recherche un fichier ,. Vous pouvez faire ce qui suit:awk -F"${your_char}"
Emixam23

1

Je suggérerais ce qui suit:

var="any given string"
N=${#var}
G=${var//g/}
G=${#G}
(( G = N - G ))
echo "$G"

Aucun appel à aucun autre programme


1

Vérifiez également ceci, par exemple nous voulons compter t

echo "test" | awk -v RS='t' 'END{print NR-1}'

ou dans python

python -c 'print "this is for test".count("t")'

ou mieux encore, nous pouvons rendre notre script dynamique avec awk

echo 'test' | awk '{for (i=1 ; i<=NF ; i++) array[$i]++ } END{ for (char in array) print char,array[char]}' FS=""

dans ce cas, la sortie est comme ceci:

e 1
s 1
t 2
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.