Zählen Sie das Vorkommen eines Zeichens in einer Zeichenfolge mit Bash

123

Ich muss die Anzahl der Vorkommen eines Zeichens in einer Zeichenfolge mit Bash zählen.

Im folgende Beispiel, wenn das Zeichen (zum Beispiel) ist t, es echos die richtige Anzahl von Vorkommen tin var, aber wenn das Zeichen Komma oder Semikolon ist, druckt es aus Null:

var = "text,text,text,text" 
num = `expr match $var [,]`
echo "$num"
Jericob
quelle
unix.stackexchange.com/questions/18736/…
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Antworten:

117

Ich würde den folgenden awkBefehl verwenden:

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

Ich Aufspalten der Zeichenfolge durch $charund die Anzahl der resultierenden Felder minus 1 drucken.

Wenn Ihre Shell den <<<Operator nicht unterstützt , verwenden Sie echo:

echo "${string}" | awk -F"${char}" '{print NF-1}'
hek2mgl
quelle
5
@ HattrickNZ Dann verwenden Sie:$(grep -o "$needle" < filename | wc -l)
hek2mgl
13
@Amir Was erwartest du?
hek2mgl
3
Sie können das überspringen wc -l, verwenden Sie grep -ces einfach , es funktioniert sowohl auf bsd grep als auch auf linux grep.
andsens
8
@andsens grep -cgibt nur die Anzahl der übereinstimmenden Zeilen aus. Es werden nicht mehrere Übereinstimmungen pro Zeile gezählt.
hek2mgl
1
Ich möchte '$' in einer Zeichenfolge zählen. Wie kann ich '$' aus der Hauptzeichenfolge entfernen?
MasT
117

Sie können zum Beispiel alle anderen Zeichen entfernen und die verbleibenden Zeichen zählen, z.

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

wird gedruckt

,,,
3

oder

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

oder

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

oder

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

oder

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

oder

perl -nle 'print s/,//g' <<<"$var"
jm666
quelle
1
einige weitere Tricks hier wiey="${x//[^s|S]}"; echo "${#y}"
Aquarius Power
4
Wenn Sie den ersten verwenden, sollten Sie immer vermeiden, einen anderen Prozess zu erzeugen, um diese Arbeit auszuführen. Dies kann die Leistung bei Verwendung mit großen Iterationsschleifen erheblich beeinträchtigen. In der Regel sollte die externe Prozessausführung ein letzter Ausweg sein, wenn iterierende oder sich wiederholende Operationen verwendet werden.
Osirisgothra
Warum magst du nicht wc? Es spielt Golf!
Ciro Santilli 法轮功 冠状 病 六四 事件 19
1
@CiroSantilli 轩 事件 法轮功 包 卓 卓 weil zum Beispielecho -n some line | wc -l
jm666
Codeblock 4 ist meiner Meinung nach der beste. Wir müssen es einfacher machen zu erreichen:tr -dc ',' <<<"$var" | wc -c
bgStack15
68

Sie können dies durch Kombinieren trund wcBefehlen tun . Zum Beispiel, um ein der Zeichenfolge zu zählenreferee

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

Ausgabe

4

Erläuterungen: Der Befehl tr -cd 'e'entfernt alle Zeichen außer 'e' und der Befehl wc -czählt die verbleibenden Zeichen.

Mehrzeiligen Eingabe sind auch gut für diese Lösung, wie Befehl cat mytext.txt | tr -cd 'e' | wc -ckann Zählungen ein der Datei mytext.txt, dachte auch die Datei viele Zeilen enthalten.

Robin Hsu
quelle
3
Ihre Lösung scheint die sauberste und am einfachsten zu merkende zu sein, danke!
Jirislav
Das ist toll. Danke dir!
Kodie Grantham
Ich liebe das, weil ich awk hasse!
Franzisk
3

Aufbauend auf den großartigen Antworten und Kommentaren aller ist dies die kürzeste und süßeste Version:

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

rmanna
quelle
2

awk funktioniert gut, wenn Ihr Server es hat

var="text,text,text,text" 
num=$(echo "${var}" | awk -F, '{print NF-1}')
echo "${num}"
user2508516
quelle
Nur als Hinweis: awk -F,sucht nach einem ,. Sie können Folgendes tun:awk -F"${your_char}"
Emixam23
1

Ich würde folgendes vorschlagen:

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

Kein Aufruf eines anderen Programms

Mathew PV
quelle
1

Schauen Sie sich das auch an, zum Beispiel wollen wir zählen t

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

oder in python

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

oder noch besser, wir können unser Skript mit dynamisieren awk

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

In diesem Fall sieht die Ausgabe folgendermaßen aus:

e 1
s 1
t 2
Freeman
quelle