Bash: Entfernen Sie den nachgestellten Zeilenumbruch von der Ausgabe

187

Wenn ich Befehle in Bash ausführe (oder genauer gesagt wc -l < log.txt), enthält die Ausgabe einen Zeilenumbruch danach. Wie werde ich es los?

Hexacyanid
quelle

Antworten:

248

Wenn Ihre erwartete Ausgabe eine einzelne Zeile ist , können Sie einfach alle Zeilenumbrüche aus der Ausgabe entfernen. Es ist nicht ungewöhnlich, an das Dienstprogramm 'tr' oder, falls bevorzugt, an Perl weiterzuleiten:

wc -l < log.txt | tr -d '\n'

wc -l < log.txt | perl -pe 'chomp'

Sie können auch die Befehlsersetzung verwenden, um die nachfolgende neue Zeile zu entfernen:

echo -n "$(wc -l < log.txt)"

printf "%s" "$(wc -l < log.txt)"

Bitte beachten Sie, dass ich mit der Entscheidung des OP, die akzeptierte Antwort zu wählen, nicht einverstanden bin. Ich glaube, man sollte es nach Möglichkeit vermeiden, 'xargs' zu verwenden. Ja, es ist ein cooles Spielzeug. Nein, das brauchst du hier nicht.


Wenn Ihre erwartete Ausgabe mehrere Zeilen enthalten kann , müssen Sie eine andere Entscheidung treffen:

Wenn Sie MEHRERE Zeilenumbrüche am Ende der Datei entfernen möchten, verwenden Sie erneut die cmd-Ersetzung:

printf "%s" "$(< log.txt)"

Wenn Sie das letzte Zeilenumbruchzeichen strikt aus einer Datei entfernen möchten, verwenden Sie Perl:

perl -pe 'chomp if eof' log.txt


Beachten Sie, dass Sie, wenn Sie sicher sind, dass Sie ein nachfolgendes Zeilenumbruchzeichen entfernen möchten, mit 'head' von GNU coreutils alles außer dem letzten Byte auswählen können. Das sollte ziemlich schnell gehen:

head -c -1 log.txt

Der Vollständigkeit halber können Sie mit 'cat' und dem Flag 'show-all' schnell überprüfen, wo sich Ihre Zeilenumbrüche (oder andere Sonderzeichen) in Ihrer Datei befinden. Das Dollarzeichen gibt das Ende jeder Zeile an:

cat -A log.txt
Steve
quelle
Dadurch werden ALLE Zeilenumbrüche aus der Ausgabe entfernt, nicht nur die nachfolgende Zeilenumbruch, wie der Titel verlangt.
Cody A. Ray
@ CodyA.Ray: Sie müssen jedoch zustimmen, dass die Frage einen bestimmten Befehl beschreibt, der immer nur eine einzige Ausgabezeile erzeugt. Ich habe meine Antwort jedoch aktualisiert, um sie dem allgemeineren Fall anzupassen. HTH.
Steve
3
Dies wäre besser, wenn die kurzen Optionen durch lange Optionen ersetzt würden. Die langen Optionen lehren sowie funktionieren zB tr --delete '\n'.
Elijah Lynn
1
Ich habe auch| tr -d '\r'
AlikElzin-Kilaka
Es ist erwähnenswert, dass die cmd-Substitutionslösung zu einer überlangen Linie führen kann, wenn die Datei sehr groß ist.
Phk
88

Einweg:

wc -l < log.txt | xargs echo -n
Satya
quelle
24
Besser:echo -n `wc -l log.txt`
Satya
9
Warum ist die Befehlsausführung in Backticks besser als die Verwendung einer Pipe?
Matthew Schinckel
2
Diese entfernen nicht nur die nachfolgenden Zeilenumbrüche, sondern drücken auch alle aufeinanderfolgenden Leerzeichen (genauer gesagt, wie durch definiert IFS) auf ein Leerzeichen. Beispiel : echo "a b" | xargs echo -n; echo -n $(echo "a b"). Dies kann für den Anwendungsfall ein Problem sein oder auch nicht.
Musiphil
14
Schlimmer noch, wenn die Ausgabe mit beginnt -e, wird sie als Option für interpretiert echo. Es ist immer sicherer zu bedienen printf '%s'.
Musiphil
1
xargsist auf meinem System sehr langsam (und ich vermute, dass es auch auf anderen Systemen ist), kann printf '%s' $(wc -l log.txt)also schneller sein, da printfes normalerweise ein eingebautes System ist (auch weil es keine Informationsumleitung gibt). Verwenden Sie niemals Backticks, diese sind in neueren POSIX-Versionen veraltet und weisen zahlreiche Nachteile auf.
yyny
13

Es gibt auch direkte Unterstützung für das Entfernen von Leerzeichen bei der Substitution von Bash-Variablen :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
Andrey Taranov
quelle
1
Sie können auch verwendentrailing_linebreak_removed=${testvar%?}
PairedPrototype
Beachten Sie, dass Sie bei Verwendung der Befehlssubstitution nichts tun müssen, um nachfolgende Zeilenumbrüche zu entfernen. Bash macht das bereits im Rahmen der Befehlsersetzung: gnu.org/software/bash/manual/html_node/…
Michael Burr
10

Wenn Sie die Ausgabe einer Variablen zuweisen, bashwerden Leerzeichen automatisch entfernt:

linecount=`wc -l < log.txt`
nneonneo
quelle
10
Nachfolgende Zeilenumbrüche werden entfernt, um genau zu sein. Es ist die Befehlsersetzung, die sie entfernt, nicht die Variablenzuweisung.
Chepner
2
Ich habe in Cygwin Bash gesehen, dass das nachfolgende Leerzeichen bei Verwendung von $ nicht entfernt wurde (cmd / c echo% VAR%). In diesem Fall musste ich $ {var %% [[: space:]]} verwenden.
Andrey Taranov
1
Hinweis: Es ist nicht die Variablenzuweisung, sondern die Ausdruckserweiterung, die Zeilenumbrüche entfernt.
Ciro Santilli 法轮功 冠状 病 六四 事件 26
10

printf schneidet bereits die nachfolgende Newline für Sie ab:

$ printf '%s' $(wc -l < log.txt)

Detail:

  • printf druckt Ihren Inhalt anstelle des %sString-Platzhalters.
  • Wenn Sie ihm nicht sagen, dass er eine neue Zeile ( %s\n) drucken soll , wird dies nicht der Fall sein .
zero2cx
quelle
7
Wenn Sie doppelte Anführungszeichen um den Befehl wie setzen "$(command)", werden die internen Zeilenumbrüche bewahrt werden - und nur die hintere Newline entfernt werden. Die Shell erledigt hier die ganze Arbeit - printfist nur eine Möglichkeit, die Ergebnisse der Befehlssubstitution zurück zu leiten stdout.
Nobar
2
Es ist nicht printf, das hier die neue Zeile entfernt, sondern die Shell, die dies mit dem $( )Konstrukt tut . Hier ist der Beweis:printf "%s" "$(perl -e 'print "\n"')"
Flimm
Auch hier ist zu beachten, dass die resultierende Befehlszeile möglicherweise zu lang wird.
Phk
Dies ist eine bequeme Lösung mit dem Vorschlag von @ nobar:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim
8

Wenn Sie nur die letzte neue Zeile entfernen möchten, leiten Sie Folgendes durch:

sed -z '$ s/\n$//'

sedfügt kein \0bis zum Ende des Streams hinzu, wenn das Trennzeichen auf NULvia gesetzt ist -z, während beim Erstellen einer POSIX-Textdatei (definiert als Ende in a \n) immer ein Finale \nohne ausgegeben wird -z.

Z.B:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

Und um nicht NULhinzugefügt zu beweisen :

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

Um mehrere nachfolgende Zeilenumbrüche zu entfernen, führen Sie Folgendes durch:

sed -Ez '$ s/\n+$//'
Tom Hale
quelle
Ich nehme an, dies ist eine GNU-Erweiterung, die der Mac sednicht bietet -z.
Spidey
5

Wenn Sie die Ausgabe von etwas in Bash ohne Zeilenende drucken möchten, geben Sie dies mit dem -nSchalter wieder.

Wenn Sie es bereits in einer Variablen haben, geben Sie es mit der abgeschnittenen neuen Zeile wieder :

    $ testvar=$(wc -l < log.txt)
    $ echo -n $testvar

Oder Sie können es stattdessen in einer Zeile tun:

    $ echo -n $(wc -l < log.txt)
Rastislav Hasicek
quelle
2
Die Variable ist technisch nicht erforderlich. echo -n $(wc -l < log.txt)hat den gleichen Effekt.
Chepner