Meine Textdatei sieht folgendermaßen aus:
This is one
sentence that is broken.
However this is a good one.
And this
one is
somehow, broken into
many.
Ich möchte das nachfolgende Zeilenumbruchzeichen für jede Zeile entfernen, auf die eine Zeile folgt, die mit einem Kleinbuchstaben beginnt.
Das sollte also sein:
This is one sentence that is broken.
However this is a good one.
And this one is somehow, broken into many.
Wie kann ich das machen?
Bearbeiten: Hier gibt es einige wirklich gute Antworten, aber ich habe mich dafür entschieden, die erste zu akzeptieren, die funktioniert hat und am frühesten war. Vielen Dank an alle!
Antworten:
Versuchen
wo
$NF !~ /\.$/
Übereinstimmungslinie, bei der das letzte Element nicht mit einem Punkt endet,{ printf "%s ",$0
Drucken Sie diese Zeile mit einem Leerzeichen und ohne Zeilenvorschub.next ; }
nächste Zeile holen,{print;}
und drucken Sie es aus.Ich bin sicher, dass es eine
sed
Option geben wird.Hinweis: Dies funktioniert mit Zeilen, die mit einem Punkt enden. Die Bedingung in Sätzen, die mit Großbuchstaben beginnen, wird jedoch nicht zusammengeführt. Siehe die Antwort von Stéphane Chazelas.
quelle
awk 'ORS=$NF~/\.$/?"\n":" "'
Mit
awk
:Fügen Sie das Datensatztrennzeichen nicht an jede Zeile an (ORS leer). Aber prepend einen Rekord Separator vor der aktuellen Zeile , wenn nicht in der ersten Zeile und der aktuellen Zeile nicht mit einem Kleinbuchstaben beginnen. Andernfalls stellen Sie stattdessen ein Leerzeichen voran, außer in der ersten Zeile.
quelle
And thisone issomehow, broken intomany.
weiß ich nicht,awk
aber sollten Linien<space>
zusätzlich zu verbunden werdenRS
? Oder ist das ein Benutzerfehler?In Perl:
Technisch gesehen wollten Sie "Zeilenumbruch gefolgt von Kleinbuchstaben" durch "Leerzeichen und Kleinbuchstaben" ersetzen. Dies ist der Kern des obigen Perl-Skripts:
input
.input
Variable als Ergebnis des Such- und Ersetzungsvorgangs.quelle
perl -0777 -pe 's/\n([a-z])/ $1/g'
und kann in ähnlicher Weise mit GNU sed alssed -zE 's/\n([a-z])/ \1/g'
(vorausgesetzt, die Eingabe hat keine Nullzeichen) durchgeführt werdenperl -Mopen=locale -0777 -pe 's/\n(?=[[:lower:]])/ /g'
damit es nicht auf ASCII-Buchstaben beschränkt ist.Mit können
sed
Sie einenN;P;D
Zyklus verwenden (um immer zwei Zeilen im Musterbereich zu haben, und wenn das erste Zeichen nach der neuen Zeile in Kleinbuchstaben geschrieben ist, ersetzen Sie die neue Zeile durch ein Leerzeichen) und einet
est - auf diese Weises
starten Sie den Zyklus nach jeder Ersetzung neu:quelle
N;P;D
Zyklus funktioniert, damit ich nicht noch einmal darauf eingehen werde. Der Unterschied besteht darin, dasst
- um zu überprüfen, ob etwas ersetzt wurde oder nicht - wenn der Test erfolgreich ist, wir zum Anfang des Skripts verzweigen, andernfalls bedeutet dies, dass nichts ersetzt wurde undP;D
ausgeführt wird. Lassen Sie mich wissen, wenn es noch unklar ist.Verwenden von
sed
undfmt
:Das sed-Skript fügt vor jeder Zeile, die mit einem Großbuchstaben beginnt, eine neue Zeile ein (mit Ausnahme der allerersten Eingabezeile).
sed
Die Ausgabe wird dann weitergeleitet,fmt
um die resultierenden Absätze neu zu formatieren.Alternativ verwenden,
par
wenn Sie es installiert haben. Es ist ein weiterer Absatzumformatierer, aber viel leistungsfähiger alsfmt
mit viel mehr Funktionen und Optionen.Beachten Sie, dass zwischen jedem Absatz eine Leerzeile steht. Absätze sollten durch mindestens eine Leerzeile voneinander getrennt sein. Ohne die Leerzeilen wird Ihr gesamtes Eingabebeispiel als einzelner Absatz mit mehreren Sätzen neu formatiert, z.
Wenn Sie die Leerzeilen nach der Neuformatierung entfernen müssen, leiten Sie sie einfach
sed
erneut durch. Dadurch werden jedoch ALLE Leerzeilen entfernt, einschließlich aller Zeilen, die möglicherweise in der ursprünglichen Eingabe enthalten waren. z.Bquelle
Eine andere Möglichkeit, dies zu tun, ist:
worin:
$\
=>ORS
,$/
=>IRS
=\n
,$"
=space
quelle
Python 3
Dies ist die gleiche Regex / Substitution wie Jeffs Antwort
quelle