Grep: Anzahl der Treffer pro Zeile zählen


26

Ich versuche, die Anzahl der Übereinstimmungen (in diesem Fall Vorkommen von {oder }) in jeder Zeile einer .tex-Datei zu ermitteln.

Ich weiß, dass das -oFlag nur die Übereinstimmung zurückgibt, aber es gibt jede Übereinstimmung in einer neuen Zeile zurück, sogar in Kombination mit dem -nFlag. Ich kenne nichts, durch das ich die Wiederholungen zählen könnte. Das -cFlag gibt nur die Gesamtzahl der Übereinstimmungen in der gesamten Datei zurück. Vielleicht könnte ich eine Zeile nach der anderen an grep leiten?

Antworten:


27
grep -o -n '[{}]' <filename> | cut -d : -f 1 | uniq -c

Die Ausgabe wird ungefähr so ​​aussehen:

3 1
1 2

Bedeutet 3 Vorkommen in der ersten Zeile und 1 in der zweiten.

Entnommen aus /programming//a/15366097/3378354 .


Dankeschön - Google hat eine Menge Regex-Hits auf SU gefunden, aber nicht auf SO, das nicht einmal ein Regex-Tag zu haben scheint. Das sortist nicht unbedingt notwendig, da die Ausgabe von grep nach Zeilennummer sortiert ist, aber ich denke, es hat sich zuvor bewährt uniq.
Chris H

2
Wahrscheinlich nicht markiert, regexda der reguläre Ausdruck der einfache Teil ist.
Tom Zych

Ist das eigentlich nötig sort -n? Kommt es nicht trotzdem in der Reihenfolge der Zeilennummern heraus?
Tom Zych

Du hast recht, sort -nist nicht notwendig. Vielen Dank.
Möbius

@TomZych, es stellte sich heraus, dass Sie Recht hatten, aber hätte ich gewusst, dass ich nicht gefragt hätte. Der mentale Sprung von grep zu tag: regex war vielleicht etwas zu viel.
Chris H

3

Nach dem Lesen verschiedener Lösungen denke ich, dass dies der einfachste Ansatz für das Problem ist:

while read i; do echo $i |grep -o "matchingString"| wc -l;  done < input.txt

3
Beste Lösung, meiner Meinung nach. Könnte noch mehr vereinfacht werden durch ein Rohr durch Reduktion: grep -o "matchingString" <<< $i | wc -l.
Benjamin W.

1
Dies wird allerdings um Größenordnungen langsamer sein als andere Optionen
Rahul

1

Verwendet grepeine Anforderung? Hier ist eine Alternative:

sed 's / [^ {}] // g' your_file | awk '{print NR, length}'

Das sedlöscht alle Zeichen außer {und } (dh nur {und }-Zeichen lassen) und awkzählt dann die Zeichen in jeder Zeile (die nur die {und }-Zeichen sind). So unterdrücken Sie Zeilen ohne Übereinstimmungen:

sed 's / [^ {}] // g' your_file | awk '/./ {print NR, length}'

Beachten Sie, dass meine Lösung davon ausgeht (erfordert), dass die Zeichenfolgen, nach denen Sie suchen, einzelne Zeichen sind. Möbius 'Antwort lässt sich leichter an Zeichenfolgen mit mehreren Zeichen anpassen. Außerdem schließt keine unserer Antworten das Auftreten von Zeichen / Zeichenketten von Interesse in Anführungszeichen oder ohne Escapezeichen aus. z.B,

{ "nullfunc() {}" }

Es wird angenommen, dass es vier geschweifte Klammern enthält.


grepwar nicht wirklich eine Anforderung, es war nur, wo ich anfing, nach einer Lösung zu suchen, weil es mir etwas nahes gab. Ich hatte noch nie ein Bedürfnis nach awk. Hätte ich die obige Antwort nicht verwendet, hätte ich dies als Chance zum Experimentieren genutzt - ich kann es immer noch. Was ich nicht klarstellen konnte (aber es hat keinen Einfluss auf die Antworten), ist, dass ich das Skript einmal pro Klammer ausführen wollte, um eine Nichtübereinstimmung (in der LaTeX-Quelle, hier für eine Tabelle) zu finden, in der die meisten Paare vorkommen eine einzelne Zeile.
Chris H

Ich bin mir nicht ganz sicher, was Sie mit "das Skript einmal pro Klammer ausführen" meinen, aber wenn Sie eine Klammer-Nichtübereinstimmung aufspüren möchten, möchten Sie vielleicht etwas ausprobieren sed 's/{[^{}]*}//g' your_file | grep –n '[{}]', bei dem die sedStreifen (übereinstimmend) gepaart werden. Wenn Sie geschachtelte Paare haben sed 's/{[^{}]*}//g;s/{[^{}]*}//g;s/{[^{}]*}//g;…' …, wiederholen Sie das s/{[^{}]*}//gso oft wie Ihre tiefste Verschachtelung.
Scott

Ich wollte `sed 's / [^}] // g' your_file | ausführen awk '{print NR, length}' und 's / [^ {] // g' your_file | awk '{print NR, length}'. Ich habe in der Tat ein Nest, und das Herausarbeiten der tiefsten Ebene schien mir eine lästige Pflicht zu sein. Das Verwandeln vieler Zeilen in eine Handvoll (es gibt einige Fälle, in denen die Klammern aus gültigen Gründen nur über mehrere Zeilen hinweg übereinstimmen) hat gut funktioniert (ich verwende jedit, das die passende Klammer hervorhebt - für jede Art von Klammer, die es versteht - also habe ich es wirklich getan müssen es nur eingrenzen).
Chris H
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.