Ich habe die Aufgabe, Sätze in einer Textdatei in separate Zeilen zu setzen. So etwas funktioniert fast:
cat file.txt | tr '.' '\n'
Aber ich möchte keine Punkte, Fragezeichen und Ausrufezeichen aus meinen Sätzen verlieren. Wie kann ich das zum Laufen bringen?
He asked, “What should I bring?” She replied, “A bottle of wine would be nice.” Then she hung up.
Richtiges Verhalten ist”
nach dem.
oder zu brechen?
. Ebenso „Verwendenawk
. (Es ist POSIX-konform.) Oder verwenden Siemygawk
. “, Wobei Sie nicht zwischen„ konform “wechseln müssen. und der ")". (3) Manchmal kommt "..." innerhalb eines Satzes vor. Auch (4) Angesichts des Textes: „Oh! Ich habe vergessen, den Herd auszuschalten. “Einige Leute halten dies möglicherweise für einen Satz. "Oh!" ist eindeutig kein Satz, da er weder Subjekt noch Verb enthält. Das ist aber subjektiv.Antworten:
Ich kann nicht sicher sein, ohne ein aktuelles Beispiel Ihrer Daten zu sehen, aber was Sie wahrscheinlich suchen, ist das Hinzufügen einer neuen Zeile nach jedem Auftreten von
.
,!
und?
. Ich weiß nicht, wie Sie mit Semikolons (;
) umgehen sollen, da sie nicht wirklich das Ende eines Satzes markieren. Das liegt an dir.Wie auch immer, Sie könnten versuchen
sed
:Das
s///
ist der Substitutionsoperator. Sein allgemeines Format ist ,s/pat/replacement
und es wird ersetztpat
mitreplacement
. Dasg
am Ende macht es den Ersatz bei allen Vorkommen vonpat
. Ohne sie würde es beim ersten aufhören. Das&
ist ein speziellessed
Konstrukt, das "was auch immer übereinstimmte" bedeutet. Also, hier wir ersetzen alle.
,!
oder?
mit dem, was angepasst wurde und eine neue Zeile.Wenn Ihr Text Abkürzungen wie enthalten
e.g.
kann, möchten Sie ihn möglicherweise nur ersetzen, wenn der nächste Buchstabe ein GROSSBUCHSTABEN ist:Beachten Sie, dass dies nicht mit Sätzen wie umgehen wird
Dr. Jones said hello.
richtig , da es , dass die davon ausgehen ,.
nachdemDr
definiert ein Satz gegeben , dass der nächste Buchstabe aktiviert ist. Wir nähern uns jetzt jedoch einer Komplexität, die weit über das einfache Q & A-Format hinausgeht und tatsächlich einen vollständigen Parser für natürliche Sprachen erfordert.quelle
g
am Ende enthält (da ein kurzer Satz vollständig in einer Zeile enthalten sein kann, mit anderen Dingen vor und nach). Wenn ich Ihnen +2 geben könnte, hätte ich es getan, wenn Sie nur gesagt hätten(space)*
- da einige von uns alten Leuten immer noch so tippen, wie es uns beigebracht wurde: Sätze durch zwei Leerzeichen trennen. (Auch wenn der eingegebene Text die Ausgabe von etwas wie RUNOFF istroff
, odernroff
zusätzliche Leerzeichen verwendet werden könnten, um eine Textausrichtung zu erreichen.)space*
, Antwort bearbeitet.sed 's/\([.!?]\) \([[:upper:]]\)/\1\n\2/g'
nur übereinstimmen, wenn das nächste Zeichen ein Großbuchstabe ist.Versuchen:
Bei einer Eingabe wie:
Es gibt:
(und ist POSIX).
quelle
g
Flags zu,s
aber mit dem Zusatz, dass es beide.
s in behandelt. . x
.[[:blank:]]\{1,\}
, obwohl es schön wäre, wenn Sie erklären würden, was Sie tun. Ich verstehe es, aber das OP gibt zu, ein Neuling zu sein.Verwenden Sie
sed
stattdessen:quelle
Die Aufgabe hat einige Fallstricke. Eine Option könnte sein:
Dies ersetzt die Zeichen im angegebenen Zeichensatz (
[.?!;]
fügen Sie einen Doppelpunkt hinzu oder entfernen Sie das Semikolon entsprechend Ihren Anforderungen), gefolgt von optionalen Leerzeichen (*
) durch das ersetzte Zeichen (\1
erweitert auf die Übereinstimmung zwischen\(
und\)
) und eine neue Zeile (\n
).quelle
\n
meisten der hier veröffentlichten Lösungen den Hinweis hinzufügen . (Ich habe das\?
für bearbeitet*
.)(space)*
.Versuchen:
wo
.
(Punkt) als Trennzeichen,quelle
?!
? Außerdem müssen Sie den Abstand zwischen dem Punkt und dem nächsten Satz berücksichtigen.Es gibt Leben außerhalb von Einzeilern ...
Satzteiler sind nie fertig, es gibt immer noch ein Detail zu reparieren: einen Perl-Multiliner!
also mit:
Die Ausgabe ist:
quelle
Ich hatte dieses Ding w /
fold
vor - was schnell war - aber ich erkannte, dass ich das gleiche w /xargs
w tun konnte , ohne Eingaben vorverarbeiten odersed
Verzweigungsschleifen implementieren zu müssen, wenn ich nur alles, was kein terminierendes Zeichen war, einem Backslash entkam alle nachfolgenden Leerzeichen.Die obige Anweisung entspricht also
sed
entweder der Nullzeichenfolge oder einer Abschlusssequenz für jedes Zeichen (nicht in der Sequenz) , das bei der Eingabe auftritt. Auf der rechten Seite wirdsed
entweder die Nullzeichenfolge oder die Abschlusssequenz durch for ersetzt\1
und anschließend ein Backslash eingefügt. Das Ergebnis ist, dass jedes Zeichen außer einem,.!?
wenn mindestens ein Leerzeichen folgt, einen\
Backslash-Escape-Effekt erhält . Dies schließt die\n
Ewline ein,sed
die nach jeder Ersetzung beim Schreiben in stdout eingefügt wird .Da
xargs
eine mit Backslash-\n
Escape versehene Ewline vollständig entfernt wird und die Argumente, die ihr benanntes Dienstprogramm übergibt, auf nicht entkappten Leerzeichen aufgeteilt werden,printf
werden alle satzartigen Zeichenfolgen gedruckt, diexargs
Eingaben ohne nachfolgende Leerzeichen und in einer einzelnen Zeile pro Zeile einlesen. Was mehr ist - es tut es in Chargen, die sich derARGMAX
Größe nähern - so viele wie möglich gleichzeitig. Und natürlichsed
sollte es auch seine Arbeit ziemlich schnell erledigen - es muss nur eine globale Substitution pro Eingabezeile durchgeführt werden.Die Ergebnisse sehen folgendermaßen aus:
Einige Lorem Ipsum von www.lipsum.com :
... was druckt ...
quelle
busybox
xargs
. Und es tut w /read
, aber nicht anders. Es braucht sehr wenig mehr, um es sicherer zu zitieren - ich denke, ich muss. Oder setzen Sie eintr -d \\n
zwischen dassed
undxargs
. (Ich habe es gerade in der Shell auf meinem Android-Tablet im Badezimmer gemacht, ehrlich)