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

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:

  1. 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.

  2. 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.