Wie kann ich verhindern, dass zusätzliche Zeilenumbrüche hinzugefügt werden?

17

Ich führe die folgenden 2 sedBefehle aus. Der erste fügt Zeilenvorschubzeichen hinzu, wo ich sie haben möchte, der zweite fügt Zeilenvorschubzeichen hinzu, wo ich sie haben möchte, ABER fügt am Ende der Datei ein zusätzliches hinzu, wo es vorher kein Zeichen gab.

sed -e 's|\<LIST_G_STATEMENT>|&\
|g' ${XMLDIR}/statement_tmp_1.xml > ${XMLDIR}/statement_tmp_2.xml

sed -e 's|\</LIST_G_STATEMENT>|&\
|g' ${XMLDIR}/statement_tmp_2.xml > ${XMLDIR}/statement_tmp_3.xml

Die Verwendung od -caller 3 Dateien führt zu folgender Ausgabe.

statement_tmp_1.xml (nein \nam Ende der Datei)

1314700    T   A   T   E   M   E   N   T   >   <   /   L   I   S   T   _
1314720    G   _   S   T   A   T   E   M   E   N   T   >   <   /   G   _
1314740    S   E   T   U   P   >   <   /   L   I   S   T   _   G   _   S
1314760    E   T   U   P   >   <   /   A   R   X   S   G   P   O   >
1314777

statement_tmp_2.xml (nein \nam Ende der Datei)

1314700    S   T   A   T   E   M   E   N   T   >   <   /   L   I   S   T
1314720    _   G   _   S   T   A   T   E   M   E   N   T   >   <   /   G
1314740    _   S   E   T   U   P   >   <   /   L   I   S   T   _   G   _
1314760    S   E   T   U   P   >   <   /   A   R   X   S   G   P   O   >
1315000

statement_tmp_3.xml ( \nam Ende der Datei - woher kommt sie?)

1314700    S   T   A   T   E   M   E   N   T   >   <   /   L   I   S   T
1314720    _   G   _   S   T   A   T   E   M   E   N   T   >  \n   <   /
1314740    G   _   S   E   T   U   P   >   <   /   L   I   S   T   _   G
1314760    _   S   E   T   U   P   >   <   /   A   R   X   S   G   P   O
1315000    >  \n
1315002

Ich verwende AIX 5.3

Grundsätzlich möchte ich, dass das Hinzufügen der zusätzlichen Elemente gestoppt \nwird oder dass eine Möglichkeit zum Entfernen gefunden wird.

jonnohudski
quelle
Nur eine Frage: Warum verwenden Sie in Ihrem Substitutionsmuster einen wörtlichen Zeilenvorschub, den Sie s|...|&\n|genauso gut hätten verwenden können ?
Joseph R.
1
@ JosephR. \nin der rechten Seite ist nicht tragbar.
Stéphane Chazelas
@StephaneChazelas Das ist komisch. Ist es eine Sache zwischen CR und CRLF?
Joseph R.
2
Eine Datei, die nicht mit einem Zeilenumbruch endet, ist keine Textdatei. Daher ist das Verhalten mit Textdienstprogrammen nicht festgelegt . Verwenden Sie ein perlanderes Tool, das mit Binärdaten umgehen kann.
Stéphane Chazelas
4
@ JosephR. Nein, das \<LF>ist die traditionelle und POSIX-Methode, um ein LF-Zeichen hinzuzufügen. \nwürde normalerweise ein nZeichen in etwas anderem als GNU ersetzen sed.
Stéphane Chazelas

Antworten:

10

Sie sollten sich glücklich sedschätzen, dass AIX diese fehlenden Zeilenumbrüche hinzugefügt hat.

Eine nicht leere Datei, die nicht mit einem Zeilenumbruch endet, ist keine Textdatei (zumindest gemäß der POSIX-Definition einer Textdatei), da eine Textdatei Zeilen enthalten soll und Zeilen ein (nicht zu lange) Folge von Zeichen, die durch ein Zeilenumbruchszeichen abgeschlossen werden, sodass das Verhalten von Textdienstprogrammen wie sedauf diesem nicht spezifiziert ist und in der Praxis von Implementierung zu Implementierung variiert.

Einige sedImplementierungen hätten diese unechten Zeichen nach der letzten Zeile verworfen.

AFAIK, xmlDateien sind als Textdateien gedacht, das heißt, sie wurden sednur für Sie repariert.

Wenn Sie möchten, dass diese Datei nicht mit einem Zeilenumbruch endet, können Sie auch perlandere Tools verwenden, die mit Nicht-Text-Daten umgehen können.

perl -pe 's|<LIST_G_STATEMENT>|$&\n|g'
Stéphane Chazelas
quelle
1
Der abschließende Zeilenumbruch ist hilfreich, wenn Sie erwarten, dass Ihre sedAusgabe in ein anderes Standard-Unix-Dienstprogramm umgeleitet wird . Ehrlich gesagt, habe ich nicht bemerkt sedhabe dies für Jahre , seit Bourne - Shell - Befehl Substitutionen wie $(sed 's/bas/replac/' <<<'basement')verstohlen die endgültige Newline trimmen, wenn es einen gibt. Aber es gibt Zeiten, in denen Sie es definitiv nicht wollen. zB X-Text in der Zwischenablage bearbeiten mit sed. Zu Ihrer Information, GNU sed fügt, falls verfügbar, keinen abschließenden Zeilenumbruch hinzu, wenn Sie pihn mit der -nOption verwenden, wie in dieser SE-Antwort beschrieben .
TheDudeAbides
0

So entfernen Sie den letzten Zeilenumbruch aus einer Datei dd:

printf "" | dd  of='/path/to/file' seek=<filesize_in_bytes - 1> bs=1 count=1

Um zu testen, ob eine Datei mit einem Zeilenumbruch endet, können Sie Folgendes verwenden:

tail -c 1 /path/to/file | tr -dc '\n' | wc -c

Und um die Dateigröße in Bytes zu erhalten, verwenden Sie:

wc -c < /path/to/file
Chan
quelle
0

Gemäß dieser AIX Handbuch IBM tailtut -reverse - das ist ziemlich cool aussieht. Solange sich Ihre Datei unter 20 KB befindet, sollte Folgendes funktionieren:

tail -r <file | dd bs=1 skip=1 | tail -r >file.new
mikeserv
quelle