Wie schneide ich führende und nachfolgende Leerzeichen aus jeder Zeile einer Ausgabe ab?

Ich möchte alle führenden und nachfolgenden Leerzeichen und Tabulatoren aus jeder Zeile in einer Ausgabe entfernen.

Gibt es ein einfaches Tool wie trim Ich könnte meine Ausgabe in?

Beispieldatei leiten:

test space at back test space at front TAB at end TAB at front sequence of some space in the middle some empty lines with differing TABS and spaces: test space at both ends 

Kommentare

  • Für alle, die hier nach einer Lösung zum Entfernen von Zeilenumbrüchen suchen, ist dies ein anderes Problem. Per Definition erstellt eine neue Zeile eine neue Textzeile. Daher kann eine Textzeile keine neue Zeile enthalten. Die Frage, die Sie stellen möchten, ist, wie Sie eine neue Zeile am Anfang oder Ende einer Zeichenfolge entfernen: stackoverflow.com/questions/369758 oder wie Sie Leerzeichen entfernen Zeilen oder Zeilen, die nur Leerzeichen sind: serverfault.com/questions/252921

Antwort

awk "{$1=$1;print}" 

oder kürzer:

awk "{$1=$1};1" 

Würde führende und trimmen Leerzeichen oder Tabulatorzeichen 1 und drücken Sequenzen von Tabulatoren und Leerzeichen in ein einzelnes Leerzeichen.

Dies funktioniert, da awk den gesamten Datensatz neu erstellt, wenn Sie einem der Felder etwas zuweisen (wie von print gedruckt) durch Verbinden aller Felder ($1, …, $NF) mit OFS (standardmäßig Leerzeichen).

1 (und möglicherweise einem anderen Leerzeichen) s abhängig vom Gebietsschema und der awk -Implementierung)

Kommentare

  • Semikolon auf Das zweite Beispiel ist überflüssig. Könnte verwenden: awk '{$1=$1}1'
  • @Brian, nein, die ; ist in der Standard-awk-Syntax erforderlich
  • Interessant … Von gawk, mawk und OS X wird kein Semikolon unterstützt. ‚ s awk. (Zumindest für meine Versionen (1.2, 4.1.1 bzw. 20070501))
  • Das einzige, was mir ‚ an diesem Ansatz nicht gefällt, sind Sie Verlieren Sie sich wiederholende Leerzeichen innerhalb der Zeile. Beispiel: echo -e 'foo \t bar' | awk '{$1=$1};1'
  • echo ' hello ' | xargs

Antwort

Der Befehl kann wie folgt komprimiert werden, wenn Sie GNU verwenden sed:

$ sed "s/^[ \t]*//;s/[ \t]*$//" < file 

Beispiel

Hier ist der obige Befehl in Aktion.

$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" blahblah 

Mit hexdump können Sie bestätigen, dass der Befehl sed die gewünschten Zeichen korrekt entfernt.

$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" | hexdump -C 00000000 62 6c 61 68 62 6c 61 68 0a |blahblah.| 00000009 

Zeichenklassen

Sie können auch Zeichenklassennamen verwenden, anstatt die Sätze buchstäblich wie folgt aufzulisten: [ \t]:

$ sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//" < file 

Beispiel

$ echo -e " \t blahblah \t " | sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//" 

Die meisten GNU-Tools, die reguläres expre verwenden ssions (Regex) unterstützen diese Klassen (hier mit ihrem Äquivalent im typischen C-Gebietsschema eines ASCII-basierten Systems (und nur dort)).

 [[:alnum:]] - [A-Za-z0-9] Alphanumeric characters [[:alpha:]] - [A-Za-z] Alphabetic characters [[:blank:]] - [ \t] Space or tab characters only [[:cntrl:]] - [\x00-\x1F\x7F] Control characters [[:digit:]] - [0-9] Numeric characters [[:graph:]] - [!-~] Printable and visible characters [[:lower:]] - [a-z] Lower-case alphabetic characters [[:print:]] - [ -~] Printable (non-Control) characters [[:punct:]] - [!-/:-@[-`{-~] Punctuation characters [[:space:]] - [ \t\v\f\n\r] All whitespace chars [[:upper:]] - [A-Z] Upper-case alphabetic characters [[:xdigit:]] - [0-9a-fA-F] Hexadecimal digit characters 

Using Diese anstelle von wörtlichen Sätzen scheinen immer Platzverschwendung zu sein. Wenn Sie jedoch „Bedenken haben, dass Ihr Code portabel ist oder sich mit alternativen Zeichensätzen befassen muss (denken Sie international), möchten Sie wahrscheinlich stattdessen die Klassennamen verwenden.“ .

Referenzen

Kommentare

  • Beachten Sie, dass [[:space:]] nicht äquivalent zu [ \t] in der allgemeiner Fall (Unicode usw.). [[:space:]] wird wahrscheinlich viel langsamer sein (da Unicode viel mehr Arten von Leerzeichen enthält als nur ' ' und ). Das Gleiche gilt für alle anderen.
  • sed 's/^[ \t]*//' ist nicht portierbar. Tatsächlich erfordert POSIX sogar, dass zum Entfernen einer Folge von Leerzeichen, Backslash- oder t -Zeichen und ‚ GNU sed funktioniert auch, wenn sich POSIXLY_CORRECT in der Umgebung befindet.
  • Was ist, wenn ich Zeilenumbrüche schneiden möchte? ‚ \ n \ n Text \ n \ n ‚
  • Ich mag die sed-Lösung wegen des Fehlens von andere Nebenwirkungen wie in der awk-Lösung. Die erste Variante funktioniert nicht, als ich sie jetzt in Bash unter OSX jsut ausprobiert habe, aber die Zeichenklassenversion funktioniert: sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
  • @EugeneBiryukov siehe meinen Kommentar zu Der ursprüngliche Beitrag

Antwort

xargs ohne Argumente tun dies.

Beispiel:

trimmed_string=$(echo "no_trimmed_string" | xargs) 

Kommentare

  • Dies kontrahiert auch mehrere Leerzeichen innerhalb Eine Zeile, die in der Frage
  • @roaima nicht angefordert wurde – true, aber die akzeptierte Antwort drückt auch Leerzeichen (die in der Frage nicht angefordert wurden). Ich denke, das eigentliche Problem hier ist, dass xargs nicht liefert, wenn die Eingabe Backslashes und einfache Anführungszeichen enthält.
  • @don_crissti, das nicht ‚ bedeutet jedoch nicht, dass die akzeptierte Antwort die gestellte Frage korrekt beantwortet. Aber in diesem Fall wurde es hier nicht ‚ als Einschränkung gekennzeichnet, während dies in der akzeptierten Antwort der Fall war. Ich ‚ habe hoffentlich die Tatsache hervorgehoben, falls es ‚ für einen zukünftigen Leser relevant ist.
  • Es auch Unterbrechungen bei einfachen Anführungszeichen, doppelten Anführungszeichen und Backslash-Zeichen. Es werden auch ein oder mehrere echo -Aufrufe ausgeführt. Einige Echo-Implementierungen verarbeiten auch Optionen und / oder Backslashes … Dies funktioniert auch nur für einzeilige Eingaben.

Antwort

Wie von Stéphane Chazelas in der akzeptierten Antwort vorgeschlagen, können Sie jetzt
ein Skript /usr/local/bin/trim:

#!/bin/bash awk "{$1=$1};1" 

und erteilen Sie dieser Datei ausführbare Rechte:

chmod +x /usr/local/bin/trim 

Jetzt können Sie jede Ausgabe an trim übergeben, zum Beispiel:

cat file | trim 

(für die folgenden Kommentare: Ich habe dies zuvor verwendet: while read i; do echo "$i"; done
was ebenfalls gut funktioniert, aber weniger performant ist)

Kommentare

  • Viel Glück, wenn Ihre Datei riesig ist und / oder Backslashes enthält.
  • @don_crissti: Könnten Sie etwas mehr kommentieren? Welche Lösung würde das? besser für große Dateien geeignet sein, und wie könnte ich meine Lösung ändern, wenn die Datei Backslashes enthält?
  • Sie ‚ müssen while read -r line verwenden, um Backslashes und auch dann beizubehalten … . In Bezug auf große Dateien / Geschwindigkeit haben Sie wirklich die schlechteste Lösung ausgewählt. Ich glaube nicht, dass ‚ etwas Schlimmeres da draußen ist. ‚ Siehe die Antworten auf Warum wird eine Shell-Schleife verwendet, um schlechte Textpraktiken zu verarbeiten? , einschließlich meines Kommentars zur letzten Antwort, in der ich einen Link zu einem Geschwindigkeits-Benchmark hinzugefügt habe. Die sed Antworten hier sind IMO vollkommen in Ordnung und weitaus besser als read.
  • Sie können auch einen Alias hinzufügen / etc / profile (oder Ihr ~ / .bashrc oder ~ / .zshrc etc …) alias trim = “ awk ‚ { \ $ 1 = \ $ 1}; 1 ‚ “
  • bash können Sie #! /usr/bin/awk -f {$1=$1};1 festlegen. (Achten Sie jedoch auf Dateinamen, die = Zeichen enthalten.)

Antwort

Wenn Sie Zeilen als Variablen speichern, können Sie den Job mit bash ausführen:

Entfernen Sie führende Leerzeichen aus einer Zeichenfolge:

shopt -s extglob echo ${text##+([[:space:]])} 

Entfernen Sie nachgestellte Leerzeichen aus einer Zeichenfolge:

shopt -s extglob echo ${text%%+([[:space:]])} 

Entfernen Sie alle Leerzeichen aus einer Zeichenfolge:

echo ${text//[[:space:]]} 

Kommentare

  • Das Entfernen aller Leerzeichen aus einer Zeichenfolge entspricht nicht dem Entfernen von führenden und nachfolgenden Leerzeichen (wie in Frage).
  • Bei weitem die beste Lösung – es sind nur Bash-Buildins und keine externen Prozessgabeln erforderlich.
  • Schön. Skripte werden viel schneller ausgeführt, wenn sie nicht ‚ externe Programme (wie awk oder sed) abrufen müssen. Dies funktioniert auch mit “ modernen “ (93u +) Versionen von ksh.

Antwort

sed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//" 

Wenn Sie eine Zeile in eine Shell-Variable einlesen, read macht das bereits , sofern nicht anders angegeben .

Kommentare

  • +1 für read. Wenn Sie also beim Lesen eine Pipe erstellen, funktioniert dies: cat file | while read i; do echo $i; done
  • @rubo, außer dass In Ihrem Beispiel wird die Variable ohne Anführungszeichen auch von der Shell erneut verarbeitet. Verwenden Sie echo "$i", um den tatsächlichen Effekt von read

Antwort

Um dank eines „piped“ -Werkzeugs alle führenden und nachfolgenden Leerzeichen aus einer bestimmten Zeile zu entfernen, kann ich 3 verschiedene identifizieren Wege, die nicht vollständig gleichwertig sind. Diese Unterschiede betreffen die Zwischenräume zwischen den Wörtern der Eingabezeile. Abhängig von den erwarteten b ehaviour, Sie werden Ihre Wahl treffen.

Beispiele

Um die Unterschiede zu erklären, betrachten wir diese Dummy-Eingabezeile:

" \t A \tB\tC \t " 

tr

$ echo -e " \t A \tB\tC \t " | tr -d "[:blank:]" ABC 

tr ist wirklich ein einfacher Befehl. In diesem Fall werden alle Leerzeichen oder Tabellierungszeichen gelöscht.

awk

$ echo -e " \t A \tB\tC \t " | awk "{$1=$1};1" A B C 

awk löscht führende und nachfolgende Leerzeichen und drückt alle Leerzeichen zwischen Wörtern auf ein einzelnes Leerzeichen.

sed

$ echo -e " \t A \tB\tC \t " | sed "s/^[ \t]*//;s/[ \t]*$//" A B C 

In diesem Fall sed löscht führende und hintere Leerzeichen, ohne Leerzeichen zwischen Wörtern zu berühren.

Anmerkung:

Bei einem Wort pro Zeile erledigt tr die Aufgabe.

Kommentare

  • Keines dieser Elemente schneidet nachfolgende / führende Zeilenumbrüche durch
  • +1 für eine Liste von Lösungen mit ihrer (manchmal unerwarteten) Ausgabe.
  • @ user61382 Dies ist ziemlich spät, aber siehe meinen Kommentar zum ursprünglichen Beitrag.
  • @highmaintenance: Verwenden Sie [:space:] anstelle von [: blank:] für den Befehl tr, wie: ... | tr -d [:space:], um auch Zeilenumbrüche zu entfernen. (siehe: man tr)

Antwort

sed ist a Tolles Tool dafür:

 # substitute ("s/") sed "s/^[[:blank:]]*//; # parts of lines that start ("^") with a space/tab s/[[:blank:]]*$//" # or end ("$") with a space/tab # with nothing (/) 

Sie können es für Ihren Fall verwenden, indem Sie entweder den Text weiterleiten, z. B.

<file sed -e "s/^[[... 

oder indem Sie „inline“ darauf reagieren, wenn Ihre sed die GNU ist:

sed -i "s/..." file 

, aber das Ändern der Quelle auf diese Weise ist „gefährlich“, da es möglicherweise nicht wiederherstellbar ist, wenn es nicht richtig funktioniert (oder sogar wenn es funktioniert!). Sichern Sie also zuerst (oder verwenden Sie -i.bak, was auch den Vorteil hat, auf einige BSDs portierbar zu sein sed s)!

Antwort

Eine Antwort, die Sie auf einen Blick verstehen können:

#!/usr/bin/env python3 import sys for line in sys.stdin: print(line.strip()) 

Bonus: Ersetzen Sie str.strip([chars]) mit beliebigen Zeichen zum Trimmen oder Verwenden von .lstrip() oder .rstrip() nach Bedarf.

Wie rubo77 „sa nswer , speichern Sie als Skript /usr/local/bin/trim und erteilen Sie Berechtigungen mit chmod +x.

Antwort

Wenn die Zeichenfolge, die getrimmt werden soll, kurz und kontinuierlich / zusammenhängend ist, kann sie einfach als Parameter übergeben werden zu jeder Bash-Funktion:

 trim(){ echo $@ } a=" some random string " echo ">>`trim $a`<<" Output >>some random string<< 

Antwort

Ich habe diese Shell-Funktion mit geschrieben awk

awkcliptor(){ awk -e "BEGIN{ RS="^$" } {gsub(/^[\n\t ]*|[\n\t ]*$/,"");print ;exit}" "$1" ; } 

BEGIN{ RS="^$" }:
am Anfang vor dem Parsen des Datensatztrennzeichens
auf none setzen dh behandeln Sie die gesamte Eingabe als
einen einzelnen Datensatz

gsub(this,that):
Ersetzen Sie diesen regulären Ausdruck durch diese Zeichenfolge

/^[\n\t ]*|[\n\t ]*$/:
dieser Zeichenfolge fängt einen beliebigen Zeilenumbruch und eine Tabulatorklasse ab
oder postet einen Zeilenumbruch und eine Tabulatorklasse und ersetzt sie durch eine leere Zeichenfolge

print;exit: Drucken und beenden Sie

"$1":
und übergeben Sie das erste Argument der Funktion an Be
process by awk

Verwendung:
Kopieren Sie den obigen Code, fügen Sie ihn in die Shell ein und geben Sie ihn dann ein, um ihn zu definieren die Funktion.
dann können Sie awkcliptor als Befehl mit dem ersten Argument als Eingabedatei verwenden.

Beispielverwendung:

echo " ggggg " > a_file awkcliptor a_file 

Ausgabe:

ggggg 

oder

echo -e "\n ggggg \n\n "|awkcliptor 

Ausgabe:

ggggg 

Kommentare

  • Können Sie den Unterschied bitte nur awk '{$1=$1};1' erklären?

Antwort

Wenn Sie nicht genügend Platz im Gehirn haben, um sich an die obskure sed-Syntax zu erinnern, kehren Sie einfach die Zeichenfolge um Schneiden Sie das erste Feld mit einem Trennzeichen aus und kehren Sie es wieder um.

cat file | rev | cut -d" " -f1 | rev 

Kommentare

  • Dies funktioniert nur, wenn nicht mehr als ein Leerzeichen vor jeder Zeile und nicht mehr als ein Wort in einer Zeile steht.

Antwort

trimpy () { python3 -c "import sys for line in sys.stdin: print(line.strip())" } trimsed () { gsed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//" } trimzsh () { local out="$(</dev/stdin)" [[ "$out" =~ "^\s*(.*\S)\s*$" ]] && out="$match[1]" || out="" print -nr -- "$out" } # example usage echo " hi " | trimpy 

Bonus: Ersetzen Sie str.strip([chars]) durch beliebige Zeichen, um oder .rstrip() nach Bedarf.

Antwort

Der Befehl translate würde funktionieren.

cat file | tr -d [:blank:] 

Kommentare

  • Dieser Befehl ist nicht korrekt, da er entfernt alle Leerzeichen aus der Datei, nicht nur führende / nachfolgende Leerzeichen.
  • @BrianRedbeard Sie haben Recht. Dies ist immer noch eine nützliche Antwort für eine monolithische Zeichenfolge ohne Leerzeichen.

Antwort

für ein Bash-Beispiel:

alias trim="awk "{\$1=\$1};1"" 

Verwendung:

echo -e " hello\t\tkitty " | trim | hexdump -C 

Ergebnis:

00000000 68 65 6c 6c 6f 20 6b 69 74 74 79 0a |hello kitty.| 0000000c 

Kommentare

  • Die Antwort awk '{$1=$1};1' wurde vor langer Zeit gegeben. Die Idee, daraus einen Alias zu machen, wurde vor fast ebenso langer Zeit in einem Kommentar vorgeschlagen. Ja, Sie dürfen den Kommentar eines anderen in eine Antwort umwandeln. Wenn Sie dies jedoch tun, sollten Sie den Personen, die die Idee vor Ihnen veröffentlicht haben, Anerkennung zollen. Und dies ist eine so triviale Erweiterung der akzeptierten Antwort, dass sich die Mühe nicht wirklich lohnt.
  • Die Idee war, einen Alias zu erstellen. ‚ habe diese Antwort noch nicht gesehen.
  • und das zweite vom Stapel: “ Vielen Dank für das Feedback! Stimmen von Personen mit weniger als 15 Reputationen werden aufgezeichnet, ändern jedoch nicht die öffentlich angezeigte Post-Punktzahl. “

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.