Wie kann ich grep für eine Anzahl von Rohren ( ‚|‘)?
-
03-07-2019 - |
Frage
Ich habe versucht:
grep -c "\|" *.*
Aber es hat nicht funktioniert, weil es eine falsche Zählung von aufeinanderfolgenden Rohren gibt.
Wie kann ich das erreichen?
Lösung
Eine weitere Möglichkeit, mit Perl, ist:
perl -e 'while(<>){$c+=tr/|/|/};print "$c\n"' *
Nicht-Einzeiler-Format, das heißt:
while(<>){
$c += tr/|/|/
}
print "$c\n"
Die while(<>){
Linie ist Perl Magie für Linien von Dateien auf dem Befehl oder aus STDIN
lesen. Sie erhalten nach einer Weile daran gewöhnt. Die Leitung selbst geht in eine Variable namens $_
, die die Standard-Parameter für viele Perl-Befehle sind. Zum Beispiel tr
, die ganz ein bisschen wie tr(1)
arbeiten, defaults auf $_
zu arbeiten. Ich setze meine Ergebnisse in einer globalen Variablen namens $c
. (In einem vollen Programm, dann ist es am besten, es eine lexikalische Variable mit my $c = 0;
außerhalb der Schleife zu erklären.) Der +=
Bediener das Ergebnis des tr
Befehls (die Anzahl der Pipe-Zeichen in diesem Fall) auf den aktuellen Wert von $c
erstellt.
Nur mit tr(1)
ist eindeutig eine einfachere Option. ; -)
Mit *.*
ist ein DOSism, dass Sie wahrscheinlich nicht auf einem UNIX-ähnlichen Plattform verwenden möchten.
Mit Apostrophe die Shell das Pipe-Zeichen liest ein bisschen besser interpretieren zu vermeiden ist. So testete ich meine Antwort mit:
$ echo '||||
|||||' | perl -e 'while(<>){$c+=tr/|/|/};print "$c\n"'
9
Andere Tipps
Sie können tr(1)
verwenden, um alle nicht-Pipe-Zeichen zu löschen und dann wc(1)
benutzen Sie insgesamt:
cat *.* | tr -d -c '|' | wc -c
Es ist eingängig, aber in den meisten Unix-regex, die |
Flucht macht es den oder-Operator. So Ihre Linie ist eigentlich „nichts oder nichts“ passende (Sie können dies testen, indem sie einige Alternativen auf jeder Seite hinzufügen). Verwenden Sie einfach
grep -c "|" *.*
Zweitens grep zählt Zeilen, keine Zeichen Ereignisse. Sie könnten ein anderes Werkzeug verwenden; oder, wenn Sie auf grep bestehen, könnten Sie setzen jedes „|“ in einer eigenen Zeile. Zum Beispiel mit sed:
sed 's/|/|\n/g' *.*
Hinweis: Wenn sed verwendet, rate ich ein Los die Prüfung sicherstellen, dass es das tut, was Sie denken, es tut. Ich musste nur dann.
Schließlich kombinieren die Zutaten:
cat *.* | sed 's/|/|\n/g' | grep -c "|"
Leider kann dies nicht für Sie arbeiten, wie Sie wahrscheinlich nicht mit UNIX (wegen der *.*
). Aber hoffentlich erklärt es das Problem, das ich immer seltsam beruhigend finden.
Wenn Sie eine Anzahl von Rohren zu finden, dann
fgrep -o "|" | wc -l
Wenn Sie eine Anzahl von Leitungen mit mindestens einem Rohr zu finden, dann
fgrep -c "|"
Versuch
grep -c "\|" *.*
und einige Tutorials über bash lesen