Text mit Echo ohne neue Zeile anhängen

14

Ich möchte Text an eine Datei anhängen echo "abc" >>file.txt.

Dies füge aber abcnach einer neuen Zeile hinzu

Wie kann ich abcam Ende der Datei mit Echo ohne neue Zeile hinzufügen ?

choijj
quelle
2
Die Datei enthält bereits einen Zeilenumbruch. Sie fügen ihn nur noch hinzu. Sie müssen also das Zeilenumbruchzeichen aus der letzten Zeile durch "abc" ersetzen.
Strg-Alt-Delor
Willkommen bei StackExchange! Ihre Frage ist gut; Es wäre besser gewesen, wenn Sie Beispiele für den Inhalt Ihrer Datei angegeben hätten (vor dem Hinzufügen, was Sie nach dem Hinzufügen erhalten, was Sie stattdessen möchten). Ich sage das, weil eine der Antworten darin besteht, wie man abcohne eine letzte neue Zeile hinzufügt, was (nachdem man Ihre Frage aufmerksam gelesen hat) nicht so zu sein scheint, wie Sie es wollen.
Law29

Antworten:

19

echo "abc" >>file.txtSetzt einen Zeilenumbruch nach abc , nicht vorher. Wenn Sie am Ende abceine eigene Zeile haben, bedeutet dies, dass die vorherige Zeile abcbereits in vorhanden war file.txt.

Beachten Sie, dass es völlig normal ist, dass eine Textdatei in einer neuen Zeile endet. Unter Unix besteht eine Zeile aus einer Folge von anderen Zeichen als null⁰ oder newline, gefolgt von einer newline. 1 Daher endet jede nicht leere Textdatei mit einem Zeilenumbruch.

Wenn Sie der letzten Zeile einer Datei Text hinzufügen möchten, können Sie dies nicht tun >>, da dieser immer an die Datei angehängt wird und daher immer nach der letzten neuen Zeile geschrieben wird. Stattdessen benötigen Sie ein Tool, mit dem Sie eine vorhandene Datei ändern können. Beispielsweise können Sie sed verwenden :

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt

Im sed-Befehl $bedeutet das erste " s/REGEX/REPLACEMENT/Führe den folgenden Befehl nur in der letzten Zeile aus", der Befehl ersetzt REGEX durch REPLACEMENT und der reguläre Ausdruck $stimmt am Ende der Zeile überein.

Der sed-Befehl von Linux verfügt über eine integrierte Funktion zum Automatisieren dieser Sequenz zum Erstellen neuer Dateien und zum Ersetzen. Sie können diese Sequenz also auf verkürzen

sed -i '$ s/$/abc/' file.txt

Das ist ein Null-Byte, das von ASCII als NUL und von Unicode als U + 0000 bezeichnet wird. Textverarbeitungsprogramme können mit diesem Zeichen zurechtkommen oder nicht.
1 Siehe die Definitionen von Textdatei , Linie und Newline - Zeichen im Abschnitt „Definitionen“ der Basis Definitionen Kapitel IEEE 1.003,1-2.008: 2016.

Gilles 'SO - hör auf böse zu sein'
quelle
2
Soll Ihr zweiter Absatz bedeuten, dass eine Datei, die nicht mit einem Zeilenumbruch endet, keine Textdatei ist? Wenn ich beispielsweise eine vorhandene ASCII-Textdatei, die mit einer neuen Zeile endet, nehme und ein einzelnes Byte 0x41(ASCII 'A') anhänge , handelt es sich technisch gesehen nicht mehr um eine Textdatei? Wenn ja, würde ich vorschlagen, diesen Punkt zu betonen, da es eine Art unintuitive Definition ist. Andernfalls kann eine geringfügige Änderung der Formulierung helfen, die Verwirrung zu vermeiden.
David Z
2
@DavidZ: Das ist die Standarddefinition einer Textdatei in Unixland. IIRC gibt es sogar irgendwo in POSIX.
Kevin
1
@ Kevin Interessant, das hatte ich noch nie gehört. Nun, auch wenn es Standard ist, denke ich, dass es irgendwie nicht intuitiv ist.
David Z
15

Ich denke nicht, dass es mit dem echoBefehl möglich ist, sondern mit dem folgenden sedAnsatz:

sed -i '$ s/$/abc/' file.txt
  • -i- Ändern Sie die Datei an Ort und Stelle
  • $ - Geben Sie den letzten Datensatz / die letzte Zeile an
  • s/$/abc/- Ersetze das Ende der Zeile $durch einen Teilstring abc(für den letzten Datensatz)
RomanPerekhrest
quelle
2
Beachten Sie, dass "an Ort und Stelle" nicht wirklich "an Ort und Stelle" bedeutet. Es bedeutet "Schreibe den bearbeiteten Inhalt in eine temporäre benannte Datei neben der vorhandenen Datei und ersetze sie dann". Sie können dies beweisen, indem Sie sich die Inodes mitdate >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
roaima 25.12.17
@roaima, mir ist bewusst, dass sed die Inode-Nummer ändert.
RomanPerekhrest
2
Ich dachte, dass Sie gewesen wären, aber ich war besorgt, dass mit Ihrer Betonung des Inplace die OP-Nacht verwendet werden könnte, um doppelten Speicherplatz zu vermeiden, z. B. mit einer großen Datei.
Roaima
@roaima, Nacht denken -> könnte denken ...
RomanPerekhrest
13

Angenommen, die Datei endet noch nicht in einer neuen Zeile und Sie möchten einfach etwas mehr Text anhängen, ohne einen hinzuzufügen, können Sie das -nArgument verwenden, z

echo -n "some text here" >> file.txt

Einige UNIX-Systeme bieten diese Option jedoch nicht an. Wenn dies der Fall ist, können Sie printfz

printf %s "some text here" >> file.txt

(Das erste %sArgument ist, sich vor dem zusätzlichen Text mit %Formatierungszeichen zu schützen. )

Von man echo(auf macOS High Sierra):

-n

Drucken Sie das nachfolgende Zeilenumbruchzeichen nicht aus. Dies kann auch erreicht werden, indem '\c'an das Ende der Zeichenfolge angehängt wird, wie dies bei iBCS2-kompatiblen Systemen der Fall ist. Beachten Sie, dass diese Option sowie der Effekt von '\c'in IEEE Std 1003.1-2001 ("POSIX.1") in der Fassung von Cor. 1-2002. Es wird dringend printf(1)empfohlen, Anwendungen zu verwenden, die auf maximale Portabilität abzielen , um den Zeilenumbruch zu unterdrücken.

flauschige
quelle
Es endet ganz offensichtlich mit einem Zeilenumbruch. echo -nwürde am Ende keinen Zeilenumbruch setzen abc, aber abcimmer noch einen Zeilenumbruch vorausgehen, was der Benutzer vermeiden möchte.
Kusalananda
@Kusalananda Meine Antwort basierte eher auf der Annahme, dass das OP versuchen würde, seinen Prozess so zu ändern, dass die Fälschungen \ngar nicht erst auftauchten. Mehr Optionen sind besser, insbesondere wenn nicht bei jeder Änderung die gesamte Datei neu geschrieben werden muss (was ziemlich langsam werden und in polynomieller Zeit ablaufen kann, wenn es wiederholt ausgeführt wird).
flauschige
9

Wenn Sie den truncateBefehl haben und Ihre Textdatei NL als letztes Zeichen enthält, können Sie ihn entfernen und Ihren Text folgendermaßen anhängen:

truncate --size -1 file.txt
echo "abc" >>file.txt

(Beachten Sie, dass truncateder Dateiinhalt keine Rolle spielt. In diesem Beispiel wird die Dateigröße lediglich um ein Byte reduziert. Wenn Ihr letztes Zeichen kein einzelnes Byte ist, dh ein "breites" Mehrbyte-Zeichen, führen Sie eine Beschädigung ein.)

Roaima
quelle
5

Was Sie wollen, ist, es am Ende der letzten Zeile, also kurz vor dem Begrenzer dieser letzten Zeile, also kurz vor dem letzten Zeichen der Datei, einzufügen.

Mit ksh93können Sie:

echo abc 1<> file >#((EOF - 1))

Wo 1<>ist der Standardoperator zum Öffnen einer Datei im Lese- und Schreibmodus (und vor allem ohne Kürzung ) auf stdout und >#((...))ist ein ksh93-spezifischer Suchoperator (hier zum Suchen vor dem letzten Byte). Beachten Sie, dass echoschreibt, abc<newline>wo das adie neue Zeile überschreibt, die dort war, und echoseine eigene neue Zeile hinzufügt.

Das zshÄquivalent:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file

Um ein genaueres Äquivalent zu erhalten, müssen Sie auch eine Fehlermeldung ausgeben, wenn die Suche fehlschlägt:

zmodload zsh/system
if sysseek -w end -u 1 -1; then
  echo abc
else
  syserror -p "$0: $LINENO: seek: "
fi 1<> file
Stéphane Chazelas
quelle
-1

Wahrscheinlich ein UUOC, aber Sie könnten auch tun:

echo "$(cat file.txt)abc" >file.txt

Gilles weist darauf hin, dass dieser Befehl begrenzt ist:

Dies funktioniert meistens, aber nicht, wenn am Ende der Datei manchmal eine Leerzeile und unmittelbar davor eine Leerzeile steht. ZB eine Datei mit einer festen Anzahl von Zeilen, bei der die letzte Zeile anfangs leer ist und sich über die Zeit erstreckt, und die vorletzte Zeile manchmal leer ist.

Seien Sie außerdem vorsichtig bei der Verwendung catvon Dateien, mit denen Sie nicht vertraut sind:

Fazit :

Verwenden Sie sed

jesse_b
quelle
2
Dies funktioniert meistens, aber nicht, wenn am Ende der Datei manchmal eine Leerzeile und unmittelbar davor eine Leerzeile steht. ZB eine Datei mit einer festen Anzahl von Zeilen, bei der die letzte Zeile anfangs leer ist und sich über die Zeit erstreckt, und die vorletzte Zeile manchmal leer ist.
Gilles 'SO- hör auf böse zu sein'
Soll ich es löschen? Ich denke auf jeden Fall, dass Roman / Ihre Antwort der richtige Weg ist, aber ich weiß, dass ich persönlich gerne Alternativen sehe, und OP hat gefragt echo: p
jesse_b
1
Auch Dadurch wird die gesamte Datei auf der Kommandozeile
n.caillou
@ n.caillou huh? Dies druckt nichts zu STDOUT.
Jesse_b
2
Nun, keine dieser Schwachstellen hängt wirklich damit zusammen cat, sondern mit Problemen, bei denen beliebige Escape-Sequenzen an das Terminal gesendet werden.
ilkkachu