wie man Text am Anfang jedes Absatzes in Bash einfügt
1292
OB7
Ich habe eine Datei mit mehreren Absätzen, die durch Leerzeilen getrennt sind. Technisch sind sie keine Absätze, sondern Textabschnitte, die durch Leerzeilen getrennt sind.
Ich möchte die Absätze sozusagen nummerieren, indem ich in die erste Zeile jeder Zeile nach einer Leerzeile eine Nummer einstelle. Also wenn meine Datei sagt:
Das ist Text. Dies ist mehr Text. Noch mehr Text! Dies ist Text in Abschnitt zwei. Noch mehr Text. Sie bekommen den Punkt ...
Ich möchte es sagen lassen:
1Dies ist Text das ist mehr text Noch mehr Text! 2Dies ist Text in Abschnitt zwei. Noch mehr Text. Sie bekommen den Punkt ...
2 Antworten auf die Frage
1
Cyrus
Versuchen Sie dies mit bash Builtin-Befehlen:
#!/bin/bash l=1 # paragraph counter echo -n $l # print paragraph counter without new line while read x; do # read current line from file, see last line if [[ $x == "" ]]; then # empty line? echo # print empty line read x # read next line from file, see last line ((l++)) # increment paragraph counter echo -n $l # print paragraph counter without new line fi echo "$x" # print current line done < file
Gut gemacht! Ich hätte es nie so angegangen. Funktioniert perfekt, danke.
OB7 vor 9 Jahren
0
1
terdon
Im Allgemeinen ist die Verwendung der Shell für die Textanalyse sehr langsam und umständlich. Hier sind einige andere Optionen:
Perl im "Absatzmodus"
perl -00pe 's/^/$./' file
Erläuterung
Der -00Absatzmodus wird aktiviert, in dem "Zeilen" durch aufeinander folgende \n\nAbsätze definiert werden . Das s/^/$./wird den Zeilenanfang ( ^) durch die aktuelle "Zeile" (Absatz) -Nummer ersetzen $.. Der -pBefehl perl, jede Zeile der Eingabedatei zu drucken, nachdem das darin angegebene Skript ausgeführt wurde -e.
Awk
awk -vRS='\n\n' -vORS='\n\n' '' file
Erläuterung
-vRS='\n\n'setzt das Datensatztrennzeichen von awk auf aufeinanderfolgende Zeilenumbrüche. Wie beim Absatzmodus von perl werden Absätze als "Zeilen" behandelt. Wir sagen dann, dass die aktuelle Zeilennummer ( NR) und die aktuelle "Zeile" gedruckt werden sollen $0. Damit wird -vORS=das Ausgabesatz-Trennzeichen auf aufeinanderfolgende Zeilenumbrüche gesetzt, so dass Absätze in der Ausgabe ebenfalls durch Leerzeilen getrennt werden. Beachten Sie, dass dadurch am Ende der Ausgabe 2 leere Zeilen hinzugefügt werden. Um dies zu vermeiden, können Sie Folgendes verwenden head:
awk -v RS='\n\n' -vORS='\n\n' '' file | head -n -2
Zum Vergleich: Hier sind die Zeiten, die die verschiedenen Lösungen auf meinem System in Anspruch genommen haben, wenn sie mit einer 10M-Testdatei ausgeführt wurden:
$ time a.sh > /dev/null ## a.sh is Cyrus's solution real 0m1.419s user 0m1.308s sys 0m0.104s $ time perl -00pe 's/^/$./' file > /dev/null real 0m0.087s user 0m0.084s sys 0m0.000s $ time awk -v RS='\n\n' -vORS='\n\n' '' file | head -n -2 >/dev/null real 0m0.074s user 0m0.056s sys 0m0.020s
Wie Sie oben sehen können, sind sowohl die Perl- als auch die awk-Lösung eine Größenordnung schneller als der Shell-Ansatz.