Ich habe eine Reihe von txt-Dateien. Ich möchte sie in Kleinbuchstaben ausgeben, nur in alphabetischer Reihenfolge und mit einem Wort pro Zeile. Ich kann dies mit mehreren tr
Befehlen in einer Pipeline wie der folgenden tun :
tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'
Ist dies in einem Scan möglich? Ich konnte ein C - Programm zu schreiben , dies zu tun, aber ich fühle mich wie es eine Möglichkeit, es zu tun mit tr
, sed
, awk
oder perl
.
Antworten:
Sie können mehrere Übersetzungen kombinieren (mit Ausnahme komplexer Fälle mit überlappenden, vom Gebietsschema abhängigen Mengen), aber Sie können das Löschen nicht mit der Übersetzung kombinieren.
Zwei Aufrufe von
tr
sind wahrscheinlich schneller als ein einzelner Aufruf komplexerer Tools. Dies hängt jedoch stark von der Eingabegröße, den Anteilen verschiedener Zeichen, der Implementierungtr
und den konkurrierenden Tools, dem Betriebssystem und der Anzahl ab von Kernen usw.quelle
tr -s '[:upper:] [:punct:]' '[:lower:]\n' <doyle_sherlock_holmes.txt
printf 'A.AAAA,A' | tr -s '[:upper:] [:punct:]' '[:lower:][\n*]'
geta\na\na'
, und die Transformation für hat... '[:lower:]\n'
möglicherweise nicht unbedingt irgendetwas zu tun'[:punct:]'
- einigetr
s kürzen set1 auf Übereinstimmung mit 2 und andere führen eine implizite Aktion aus[\n*]
. Es ist besser, nur die Reichweite dort zu nutzen.Hier einige Ansätze:
GNU
grep
undtr
: Finde alle Wörter und mache sie in KleinbuchstabenGNU grep und perl: wie oben, aber perl übernimmt die Konvertierung in Kleinbuchstaben
Perl: Finde alle alphabetischen Zeichen und drucke sie in Kleinbuchstaben aus (danke @steeldriver):
sed: Entfernen Sie alle Zeichen, die keine Buchstaben oder Leerzeichen sind, ersetzen Sie alle alphabetischen Zeichen durch ihre Kleinbuchstabenversionen und ersetzen Sie alle Leerzeichen durch Zeilenumbrüche. Beachten Sie, dass dies voraussetzt, dass alle Leerzeichen Leerzeichen und keine Tabulatoren sind.
quelle
perl -lne 'print lc for /[[:alpha:]]+/g'
funktionieren? oder ist es schlechter Stil? (Ich bin neu in Perl und versuche zu lernen!)sed -z 's/\W*\(\w\+\)\W*/\L\1\n/g'
sed
kann\w
jetzt? Cool!sed
‚s-z
ero abgrenzen Schalter - es Zyklen über\0NUL
s statt Zeilenumbrüchen. Ziemlich cool, wenn du so etwas machsttar -c . | tr -s \\0 | sed -z ...
- aber irgendwie langsam.Ja. Sie können dies mit
tr
einem ASCII-Gebietsschema tun (was für eine GNUtr
ohnehin die einzige Aufgabe ist) . Sie können die POSIX-Klassen verwenden oder die Bytewerte jedes Zeichens durch eine Oktalzahl referenzieren. Sie können ihre Transformationen auch auf Bereiche aufteilen.Der obige Befehl würde alle Großbuchstaben in Kleinbuchstaben umwandeln, Kleinbuchstaben vollständig ignorieren und alle anderen Zeichen in Zeilenumbrüche umwandeln. Natürlich haben Sie dann eine Menge Leerzeilen. Der
tr
-s
Schalter "Queeeze Repeats" kann in diesem Fall nützlich sein. Wenn Sie ihn jedoch neben der[:upper:]
to-[:lower:]
Transformation verwenden, werden auch Großbuchstaben gedrückt . Auf diese Weise benötigt es noch einen zweiten Filter wie ......oder...
... und so wird es viel weniger bequem als ...
... das die
-c
Ergänzung von alphabetischen Zeichen nacheinander zu einer einzigen neuen Zeile pro Stück zusammenpresst und dann die Transformation von oben nach unten auf der anderen Seite der Pipe durchführt.Das heißt nicht, dass Bereiche dieser Art nicht nützlich sind. Zeug wie:
... kann sehr praktisch sein, da es die Eingabebytes über ein Spreizspektrum ihrer Werte in alle Ziffern konvertiert. Verschwenden Sie nicht, wollen Sie nicht, wissen Sie.
Ein anderer Weg, um die Transformation durchzuführen, könnte beinhalten
dd
.Da
dd
sowohl Konvertierungenunblock
als auchlcase
Konvertierungen gleichzeitig ausgeführt werden können, ist es möglicherweise sogar möglich, einen Großteil der Arbeit an diese weiterzugeben. Dies kann jedoch nur dann wirklich nützlich sein, wenn Sie die Anzahl der Bytes pro Wort genau vorhersagen können - oder zumindest jedes Wort zuvor mit Leerzeichen auf eine vorhersagbare Byteanzahl auffüllen können, daunblock
am Ende jedes Blocks nachgestellte Leerzeichen verwendet werden.quelle
dd