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- odert
-Zeichen und ‚ GNUsed
funktioniert auch, wenn sichPOSIXLY_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. Diesed
Antworten hier sind IMO vollkommen in Ordnung und weitaus besser alsread
. - 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 vonread
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 Befehltr
, 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. “