So fassen Sie Dateien zusammen und fügen fehlende Zeilenumbrüche am Ende einiger Dateien hinzu

8

Ich habe eine Reihe von .textDateien, von denen die meisten mit dem Standard nl enden.

Ein Paar hat am Ende keinen Terminator. Das letzte physikalische Byte ist (im Allgemeinen) ein alphabetisches Zeichen.

Ich habe verwendet cat *.text >| /tmp/joined.text, aber dann einige Stellen in join.text bemerkt, an denen die erste Zeile einer Datei am Ende der letzten Zeile einer vorherigen Datei erschien. Bei der Überprüfung der vorherigen Datei stellte ich fest, dass es keinen Zeilenabschluss gab - die Verkettung wurde erklärt.

Das warf die Frage auf, was der einfachste Weg ist, sich zu verketten und in der fehlenden Newline zu bleiben. Was ist mit diesen Optionen?

  1. Eine Lösung, die einigen Eingabedateien möglicherweise eine leere Zeile hinzufügt. Für mich ist das kein Problem, da die Verarbeitung von join.text damit umgehen kann.
  2. Eine Lösung, die cr / fl nur zu Dateien hinzufügt, die noch nicht so enden.
HiTechHiTouch
quelle
1
Am sichersten ist es, die fehlende neue Zeile hinzuzufügen, z. B. unix.stackexchange.com/questions/31947/…. Völlig unsicher ist es, diese fehlerhaften Dateien zu belassen und sich dann zu fragen, warum eine Shell whilediese fehlerhaften letzten Zeilen überspringt.
Thrig
Willst du wirklich ein cr / lf oder willst du den normalen Standard \n? Auf * nix-Systemen enden die Zeilen mit einem einzigen \n. Das \r\nist eine Windows-Sache. Und wo willst du das? Am Ende jeder Zeile? Das Ende der Datei?
Terdon
@thrig Aber welche spezifischen Dateien? Mit anderen Worten, was ist ein guter Weg, um sie automatisch zu identifizieren (anstatt jeden einzelnen Kandidaten zu öffnen)? Und wenn versehentlich eine andere generiert wird, wäre eine automatisierte Methode besonders schön!
HiTechHiTouch
@terdon Danke für den Fang. Mein Windows-Erbe zeigt ... Das nl steht nur am Ende einer Datei, die keine hat. Jede Zeile in einer mehrzeiligen Datei endet mit Ausnahme der letzten mit nl. Wahrscheinlich, weil ein Redakteur es fallen gelassen hat.
HiTechHiTouch
@terdon diese Idee würde für Option 1 funktionieren, aber so wie ich den Suchmann gelesen habe, würde '% s \ n' die Größe der Datei anhängen. Willst du wahrscheinlich nur '\ n'?
HiTechHiTouch

Antworten:

12

Ein weiterer Befehl, der bei Bedarf Zeilenumbrüche hinzufügen kann, lautet awk:

awk 1 ./*.txt

Die 1 hier ist der einfachste Weg, um eine wahre Bedingung in awk zu erhalten, was für diesen Zweck funktioniert, da die Standardaktion von awk unter wahren Bedingungen darin besteht, die Eingabezeilen zu drucken.

muru
quelle
Hallo @muru, kannst du ein bisschen erklären, was "awk 1" bedeutet?
Jon
2
Die Standardaktion von @Jon awk unter wahren Bedingungen besteht darin, die Eingabezeilen zu drucken. Dies 1ist die einfachste wahre Bedingung. Es ist eine Abkürzung fürawk '{print}'
Muru
4

Mit einigen cutImplementierungen wie GNU cutkönnen Sie Folgendes tun:

cut -b 1- ./*.text > output

da es die fehlende neue Zeile hinzufügt, wenn sie fehlt.

Stéphane Chazelas
quelle
3

Dieser handliche Perl-Einzeiler kann den fehlenden Zeilenumbruch nur hinzufügen, wenn er noch nicht vorhanden ist:

perl -lpe '' ./*.text > output
Rakesh Sharma
quelle
1

Der erste Ansatz, der mir in den Sinn kommt, besteht darin, die Dateien zu durchlaufen und ihren Inhalt mit einer angehängten neuen Zeile zu drucken:

for f in *text; do
    printf '%s\n' "$(cat < "$f")"
done > /tmp/joined.text

Das $()wird alle bereits vorhandenen Zeilenumbrüche Streifen so diese nur zur Folge wird \nam Ende jeder Datei.

terdon
quelle
Ich möchte keine vorhandenen NLs entfernen - das würde einfach alle Zeilen zusammenlaufen lassen, was mein Problem noch verschärft. Was Sie mir sagen, ist für Option 1, durchlaufen Sie einfach alle Dateien und drucken Sie jede einzelne dann eine NL. Ich bin nicht überrascht, dass es in einem vorhandenen Dienstprogramm nicht möglich ist, eine neue Leitung zu erzwingen, wenn dies erforderlich ist, damit Leitungen nicht zusammenlaufen.
HiTechHiTouch
@HiTechHiTouch Hiermit werden alle vorhandenen entfernt \n und eine hinzugefügt. Das Ergebnis ist immer eins (und nur eins) \nam Ende jeder Datei. Das %sist eine printfSache, es bedeutet nur "String". Siehe hier . Sie verwechseln es mit [ -s file ]der Größe der Datei. Dies gilt sowohl für Option 1 als auch für Option 2. Nein, für ein Dienstprogramm gibt es keine, da jedes Programm, das in eine Datei schreibt, immer eine neue Zeile hinzufügt. Wenn es keine gibt, liegt das fast immer daran, dass etwas kaputt gegangen ist und die Datei beschädigt ist.
Terdon
1
Beachten Sie, dass eine leere Zeile für leere Dateien (oder Dateien, die nicht zum Lesen geöffnet werden können) hinzugefügt wird. In anderen Shells als zshwird es an NUL-Zeichen ersticken. Es sollte wahrscheinlich auch beachtet werden, dass es die gesamten Dateien in den Speicher lädt.
Stéphane Chazelas
0

Sie könnten dies verwenden:

grep -h "" ./*.txt

-h entfernt den Ausdruck des Dateinamens

Wadih M.
quelle