Ich habe mich gefragt, wie die Nummer eines bestimmten Zeichens in jeder Zeile von einigen Textverarbeitungsprogrammen gezählt werden soll.
Zum Beispiel, um "
in jeder Zeile des folgenden Textes zu zählen
"hello!"
Thank you!
Die erste Zeile hat zwei und die zweite Zeile hat 0.
Ein weiteres Beispiel ist das Zählen (
in jeder Zeile.
Antworten:
Sie können es mit
sed
und tunawk
:Wo
dat
ist Ihr Beispieltext, sed löscht (für jede Zeile) alle Nicht-"
Zeichen undawk
druckt für jede Zeile ihre Größe (dhlength
entsprichtlength($0)
, wo$0
bezeichnet die aktuelle Zeile).Für einen anderen Charakter müssen Sie nur den sed-Ausdruck ändern. Zum Beispiel für
(
:Update: Ist
sed
eine Art Overkill für die Aufgabe -tr
ist ausreichend. Eine äquivalente Lösung mittr
ist:Das bedeutet, dass
tr
alle Zeichen gelöscht werden, die nicht-c
im Zeichensatz enthalten sind ( Komplement bedeuten)"\n
.quelle
tr
&wc
-Version.ß
(utf hex: c3 9f) (statt"
) wie erwartet funktioniert, das heißttr
,sed
undawk
sie ergänzen / Ersatz / ohne ein Problem zu zählen - auf einem Ubuntu 10.04 - System.tr
, einschließlich GNU tr und klassischem Unix tr, arbeiten mit Einzelbyte-Zeichen und sind nicht Unicode-konform. Zitat aus Wikipedia tr (Unix) . Probieren Sie dieses Snippet aus:echo "aā⧾c" | tr "ā⧾" b
... unter Ubuntu 10.04 ...ß
ist ein Einzelbyte Erweitertes lateinisches Zeichen und wird behandelt vontr
... Das eigentliche Problem hierbei ist nicht, dasstr
Unicode nicht behandelt wird (da ALLE Zeichen Unicode sind), sondern dass jeweilstr
nur ein Byte behandelt wird.Ich würde einfach awk benutzen
Hier setzen wir das Feldtrennzeichen (mit dem -F-Flag) auf das Zeichen,
"
dann drucken wir nur die Anzahl der FelderNF
- 1. Die Anzahl der Vorkommen des Zielzeichens ist eins weniger als die Anzahl der getrennten Felder.Für lustige Zeichen, die von der Shell interpretiert werden, müssen Sie nur sicherstellen, dass Sie sie maskieren. Andernfalls versucht die Befehlszeile, sie zu interpretieren. Also für beide
"
und)
Sie müssen das Feldtrennzeichen (mit\
) zu entkommen .quelle
'
). Es hat auch ein seltsames Verhalten mit leeren Zeilen."
daher fühle ich mich verpflichtet, den Code damit arbeiten zu lassen. Es kommt darauf an, welche Shell Sie verwenden, wenn der Charakter entkommen muss, aber bash / tcsh müssen beide entkommen "-F'"'
.awk -F"$1" '{print NF==0?NF:NF-1}' filename
Mit
tr
ardwc
:Verwendungszweck:
quelle
tr
behandelt keine Zeichen, die mehr als ein Byte verwenden .. siehe Wikipedia tr (Unix) .. dh.tr
ist nicht Unicode-konform.$IFS
, andernfallsread
werden sie von Anfang bis Ende gekürzt.echo
für beliebige Daten verwendentr
Implementierungen unterstützen Multibyte-Zeichen, zählen aberwc -c
Bytes, keine Zeichen (wc -m
Zeichen erforderlich ).Noch eine andere Implementierung , die auf externe Programme nicht verlassen, in
bash
,zsh
,yash
und einige Implementierungen / Versionenksh
:Verwenden
line="${line//[!(]}"
für die Zählung(
.quelle
eof=false; IFS=; until $eof; do read -r || eof=true; echo "$REPLY"; done
/
, das in bash nicht benötigt wird. Es ist eine ksh-Anforderung?/
wird in älteren Versionen von ksh und IIRC auch in älteren Versionen von bash benötigt.Die Antworten mit
awk
fehlschlagen , wenn die Anzahl der Spiele zu groß ist (was meine Situation passiert sein). Für die Antwort von loki-astari wird folgender Fehler gemeldet:Bei der Antwort von enzotib (und der Entsprechung von manatwork ) tritt ein Segmentierungsfehler auf:
Die
sed
Lösung von maxschlepzig funktioniert korrekt, ist aber langsam (Timings unten).Einige hier noch nicht vorgeschlagene Lösungen. Erstens mit
grep
:Und mit
perl
:Hier sind einige Zeitangaben für einige der Lösungen (am langsamsten bis am schnellsten geordnet). Ich habe mich hier auf Einzeiler beschränkt. 'foo.txt' ist eine Datei mit einer Zeile und einer langen Zeichenfolge, die 84922 Übereinstimmungen enthält.
quelle
Eine andere
awk
Lösung:quelle
Eine weitere mögliche Implementierung mit awk und gsub:
Die Funktion
gsub
entspricht der von sed's///g'
.Verwenden
gsub("[^(]", "")
für die Zählung(
.quelle
awk '{print gsub(/"/,"")}' input-file
Es würde ausreichen, wenn Sie für jede Teilzeichenfolge, die dem regulären Ausdruck r in der Zeichenfolge t entspricht, die Zeichenfolge s einsetzen und die Anzahl der Ersetzungen zurückgeben. (man awk)Ich beschloss, ein C-Programm zu schreiben, weil ich gelangweilt war.
Sie sollten wahrscheinlich eine Eingabevalidierung hinzufügen, aber ansonsten ist alles festgelegt.
quelle
free(line)
weil das Beenden des Programms implizit den gesamten zugewiesenen Speicher freigibt - dann ist Platz für einreturn 0;
...;). Selbst in Beispielen ist es nicht gut, den Rückkehrcode undefiniert zu lassen. Übrigensgetline
ist eine GNU-Erweiterung - falls sich jemand wundert.f
, die mehrmals von einem anderen Code aufgerufen wird, müssen Siefree
nach dem letzten Aufruf vongetline
am Ende dieser Funktion aufrufenf
.Für eine Zeichenfolge wäre die einfachste mit
tr
undwc
(kein Overkill mitawk
odersed
) - aber beachten Sie die obigen Kommentare zutr
, zählt Bytes, nicht Zeichen -Dabei
$x
handelt es sich um die Variable, die die auszuwertende Zeichenfolge (keine Datei) enthält.quelle
Hier ist eine andere C-Lösung, die nur STD C und weniger Speicher benötigt:
quelle
\n
ist keine echte Zeile. Dies ist das gleiche Verhalten wie bei meiner anderen Antwort sed / awk (tr / awk).Wir können
grep
mit verwendenregex
, um es einfacher und leistungsfähiger zu machen.Um ein bestimmtes Zeichen zu zählen.
Zum Zählen von Sonderzeichen einschließlich Leerzeichen.
Hier wählen wir ein beliebiges Zeichen mit
[\S\s]
und mit der-o
Option, dass wirgrep
jede Übereinstimmung (dh jedes Zeichen) in einer separaten Zeile ausgeben. Und dann verwenden,wc -l
um jede Zeile zu zählen.quelle
"
in jeder Zeile sind; und für alle anderen Zeichen. siehe seine frage und auch akzeptierte antwort.Vielleicht wäre eine einfachere, rein unkomplizierte Antwort die Verwendung von Split. Split nimmt einen String und verwandelt ihn in ein Array. Der Rückgabewert ist die Anzahl der generierten Array-Elemente + 1.
Der folgende Code gibt die Anzahl der Ausdrucke aus "wird in jeder Zeile angezeigt.
Weitere Informationen zu split http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_92.html
quelle
Hier ist ein einfaches Python-Skript, mit dem Sie die Anzahl
"
in jeder Zeile einer Datei ermitteln können:Hier haben wir die
count
Methode des eingebautenstr
Typs verwendet.quelle
Für eine reine Bash-Lösung (jedoch bash-spezifisch): Wenn
$x
die Variable Ihren String enthält:Das
${x//
Ding entfernt alle Zeichen außer"
,${#x2}
berechnet die Länge dieser Pause.(Ursprünglicher Vorschlag mit
expr
dem es Probleme gibt, siehe Kommentare:)quelle
expr
und Bytes zählt, keine Zeichen. Mit anderenexpr
:expr "x${x...}" : "x.*" - 1
Ersetzen Sie
a
durch das zu zählende Zeichen. Ausgabe ist der Zähler für jede Zeile.quelle
Zeitvergleich der vorgestellten Lösungen (keine Antwort)
Die Effizienz der Antworten ist nicht wichtig. Trotzdem habe ich nach dem @ josephwb-Ansatz versucht, alle vorgestellten Antworten zeitlich abzustimmen.
Als Eingabe verwende ich die portugiesische Übersetzung von Victor Hugo "Les Miserables" (großes Buch!) Und zähle die Vorkommen von "a". Meine Ausgabe hat 5 Bände, viele Seiten ...
C-Antworten wurden mit gcc zusammengestellt (keine Optimierungen).
Jede Antwort wurde dreimal ausgeführt und die beste ausgewählt.
Vertraue diesen Zahlen nicht zu sehr (meine Maschine erledigt andere Aufgaben usw. usw.). Ich teile diese Zeiten mit Ihnen, weil ich einige unerwartete Ergebnisse habe und ich bin sicher, dass Sie noch mehr finden werden ...
grep -oP a
ist Baum mal schneller alsgrep -o a
(10; 11 vs 12)(ergibt eine zufällige Reihenfolge)
quelle
wo grep all das schwere heben macht: meldet jedes Zeichen, das in jeder Zeilennummer gefunden wurde. Der Rest besteht nur darin, die Anzahl pro Zeile zu summieren und die Ausgabe zu formatieren.
Entfernen Sie die
-n
und erhalten Sie die Zählung für die gesamte Datei.Das Zählen einer 1,5-Megabyte-Textdatei in weniger als 0,015 Sekunden scheint schnell zu sein.
Und arbeitet mit Zeichen (nicht Bytes).
quelle
Eine Lösung für Bash. Kein externes Programm aufgerufen (schneller für kurze Zeichenfolgen).
Wenn sich der Wert in einer Variablen befindet:
Dies gibt aus, wie viele
"
es enthält:quelle