Ich habe ein Shell-Skript mit diesem Code:
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
Der bedingte Code wird jedoch immer ausgeführt, da hg st
immer mindestens ein Zeilenumbruchzeichen gedruckt wird.
- Gibt es eine einfache Möglichkeit, Leerzeichen zu entfernen
$var
(wietrim()
in PHP )?
oder
- Gibt es eine Standardmethode für den Umgang mit diesem Problem?
Ich könnte sed oder AWK verwenden , aber ich würde gerne glauben, dass es eine elegantere Lösung für dieses Problem gibt.
$ var=$(echo)
$ [ -n $var ]; echo $? #undesired test return
0
$ [[ -n $var ]]; echo $?
1
echo " This is a string of char " | xargs
. Wenn Sie jedoch ein einfaches Anführungszeichen im Text haben, können Sie Folgendes tun :echo " This i's a string of char " | xargs -0
. Beachten Sie, dass ich die neuesten xargs (4.6.0)test=`echo`; if [ -n "$test" ]; then echo "Not empty"; fi
, dies wird jedochtest=`echo "a"`; if [ -n "$test" ]; then echo "Not empty"; fi
- also muss am Ende mehr als nur eine neue Zeile stehen.echo $A | sed -r 's/( )+//g'
;Antworten:
Definieren wir eine Variable, die führende, nachfolgende und mittlere Leerzeichen enthält:
So entfernen Sie alle Leerzeichen (gekennzeichnet mit
[:space:]
intr
):So entfernen Sie nur führende Leerzeichen:
So entfernen Sie nur nachgestellte Leerzeichen:
So entfernen Sie sowohl führende als auch nachfolgende Leerzeichen - verketten Sie die
sed
s:Alternativ kann , wenn Ihre bash unterstützt wird , können Sie ersetzen
echo -e "${FOO}" | sed ...
mitsed ... <<<${FOO}
, wie so (für nachfolgende Leerzeichen):quelle
tr
undsed
durch[[:space:]]
. Beachten Sie, dass dersed
Ansatz nur für einzeilige Eingaben funktioniert . Informationen zu Ansätzen, die mit mehrzeiligen Eingaben funktionieren und auch die integrierten Funktionen von bash verwenden, finden Sie in den Antworten von @bashfu und @GuruM. Eine verallgemeinerte Inline-Version von @Nicholas Sushkins Lösung würde folgendermaßen aussehen:trimmed=$([[ " test test test " =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]; echo -n "${BASH_REMATCH[1]}")
alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"
an Ihre und verwenden .~/.profile
echo $SOMEVAR | trim
cat somefile | trim
sed
Lösung geschrieben, die nur einen einzigen Ausdruck anstelle von zwei verwendet :sed -r 's/^\s*(\S+(\s+\S+)*)\s*$/\1/'
. Es schneidet führende und nachfolgende Leerzeichen ab und erfasst alle durch Leerzeichen getrennten Sequenzen von Nicht-Leerzeichen in der Mitte. Genießen!|
um ihn als einen einzelnen Ausdruck und nicht als mehrere auszudrücken.Eine einfache Antwort lautet:
Xargs erledigt das Trimmen für Sie. Es ist ein Befehl / Programm, keine Parameter, gibt den zugeschnittenen String zurück, so einfach ist das!
Hinweis: Dadurch werden nicht alle internen Leerzeichen entfernt, sodass sie
"foo bar"
gleich bleiben. es wird NICHT"foobar"
. Es werden jedoch mehrere Räume zu einzelnen Räumen zusammengefasst, so"foo bar"
dass dies auch der Fall ist"foo bar"
. Außerdem werden keine Zeilenendezeichen entfernt.quelle
xargs echo
pfeifen, um ausführlich zu sagen, was ich tue, aber xargs alleine verwendet standardmäßig Echo.sed 's/ *$//'
als Alternative empfehlen . Sie können die sehenxargs
Newline wie folgt aus :echo -n "hey thiss " | xargs | hexdump
Sie werden feststellen ,0a73
dasa
die Neue - Zeile ist. Wenn Sie dasselbe tun mitsed
:echo -n "hey thiss " | sed 's/ *$//' | hexdump
Sie werden sehen0073
, keine neue Zeile.a<space><space>b
ina<space>b
. 2. Noch mehr: es wird sicha"b"c'd'e
inabcde
. 3. Noch mehr: es wird ama"b
usw. scheiternEs gibt eine Lösung, die nur Bash-integrierte Funktionen verwendet, die als Platzhalter bezeichnet werden :
Hier ist das gleiche in einer Funktion verpackt:
Sie übergeben die zu schneidende Zeichenfolge in Anführungszeichen. z.B:
Das Schöne an dieser Lösung ist, dass sie mit jeder POSIX-kompatiblen Shell funktioniert.
Referenz
quelle
s=" 1 2 3 "; echo \""${s%1 2 3 }"\"
würde alles vom Ende abschneiden und die Führung zurückgeben" "
. Das Subbing1 2 3
mit[![:space:]]*
sagt ihm, er solle "das erste Nicht-Leerzeichen finden, es dann und alles danach überfallen". Die Verwendung von%%
anstelle von%
macht den Trim-from-End-Vorgang gierig. Dies ist in einem nicht gierigen Trimmen von Anfang an verschachtelt, sodass Sie praktisch" "
von Anfang an trimmen . Tauschen Sie dann%, # und * gegen die Endfelder aus. Bam!/bin/sh
(nur mit/usr/xpg4/bin/sh
, aber dies wird nicht mit üblichen sh-Skripten verwendet).${var%%[![:space:]]*}
heißt es "Entfernen Sie ausvar
der längsten Teilzeichenfolge, die mit einem Nicht-Leerzeichen beginnt". Das heißt, Sie haben nur noch die führenden Leerzeichen, mit denen Sie anschließend entfernen${var#..
. Die folgende Zeile (nachlaufend) ist das Gegenteil.awk
,sed
,tr
,xargs
) nur zu trimmen Leerzeichen aus einer einzigen Saite ist grundsätzlich verrückt - vor allem , wenn die meisten Schalen (einschließlich bash) bereits bietet nativen String munging Einrichtungen out-of-the-box.Bash verfügt über eine Funktion namens Parametererweiterung , die unter anderem das Ersetzen von Zeichenfolgen anhand sogenannter Muster ermöglicht (Muster ähneln regulären Ausdrücken, es gibt jedoch grundlegende Unterschiede und Einschränkungen). [Flussences ursprüngliche Zeile: Bash hat reguläre Ausdrücke, aber sie sind gut versteckt:]
Im Folgenden wird gezeigt, wie Sie alle Leerzeichen (auch aus dem Innenraum) aus einem variablen Wert entfernen .
quelle
${var/ /}
Entfernt das erste Leerzeichen.${var// /}
Entfernt alle Leerzeichen. Es gibt keine Möglichkeit, nur führende und nachfolgende Leerzeichen mit diesem Konstrukt zu kürzen.So entfernen Sie alle Leerzeichen am Anfang und am Ende einer Zeichenfolge (einschließlich Zeichen am Zeilenende):
Dadurch werden auch doppelte Leerzeichen entfernt:
Produziert: 'Diese Saite hat viele Leerzeichen'
quelle
echo -n
überhaupt?echo " my string " | xargs
hat den gleichen Ausgang.Entfernen Sie ein führendes und ein nachfolgendes Leerzeichen
Zum Beispiel:
Ausgabe:
Entfernen Sie alle führenden und nachfolgenden Leerzeichen
Zum Beispiel:
Ausgabe:
quelle
'hello world ', 'foo bar', 'both sides '
Aus dem Abschnitt Bash Guide zum Globbing
So verwenden Sie einen Extglob in einer Parametererweiterung
Hier ist dieselbe Funktionalität, die in eine Funktion eingeschlossen ist (HINWEIS: Die an die Funktion übergebene Eingabezeichenfolge muss angegeben werden):
Verwendungszweck:
Wenn wir die Funktion ändern, die in einer Subshell ausgeführt werden soll, müssen wir uns nicht um die Prüfung der aktuellen Shell-Option für extglob kümmern, sondern können sie einfach festlegen, ohne die aktuelle Shell zu beeinflussen. Dies vereinfacht die Funktion enorm. Ich aktualisiere auch die Positionsparameter "an Ort und Stelle", damit ich nicht einmal eine lokale Variable benötige
damit:
quelle
extglob
, indem Sie Folgendes verwendenshopt -p
: Schreiben Sie einfachlocal restore="$(shopt -p extglob)" ; shopt -s extglob
am Anfang Ihrer Funktion undeval "$restore"
am Ende (außer, selbstverständlich, eval ist böse…).[[:space:]]
könnte ersetzt werden, na ja, einen Raum:${var##+( )}
und${var%%+( )}
Arbeit als gut und sie sind leichter zu lesen.Sie können einfach trimmen mit
echo
:quelle
foo
einen Platzhalter enthält? zBfoo=" I * have a wild card"
... Überraschung! Darüber hinaus werden dadurch mehrere zusammenhängende Räume zu einem zusammengefasst.Ich habe es immer mit sed gemacht
Wenn es eine elegantere Lösung gibt, hoffe ich, dass jemand sie veröffentlicht.
quelle
sed
?sed -e 's/\s*$//'
. Erläuterung: 's' bedeutet Suche, das '\ s' bedeutet alle Leerzeichen, das '*' bedeutet null oder viele, das '$' bedeutet bis zum Ende der Zeile und '//' bedeutet, alle Übereinstimmungen durch eine leere Zeichenfolge zu ersetzen .Sie können Zeilenumbrüche löschen mit
tr
:quelle
Wenn die erweiterten Mustervergleichsfunktionen von Bash aktiviert sind (
shopt -s extglob
), können Sie Folgendes verwenden:{trimmed##*( )}
um eine beliebige Anzahl von führenden Leerzeichen zu entfernen.
quelle
/bin/sh -o posix
funktioniert auch, aber ich bin misstrauisch.trimmed
? Ist es eine eingebaute Sache oder die Variable, die getrimmt wird?quelle
read
bei Variable unter seinem Namen $ 1 eine getrimmte Version seines Wertes $ {! 1}trim() { while [[ $# -gt 0 ]]; do read -rd '' $1 <<<"${!1}"; shift; done; }
read -rd '' str <<<"$str"
werden.Es gibt viele Antworten, aber ich glaube immer noch, dass mein gerade geschriebenes Skript erwähnenswert ist, weil:
"$*"
Verknüpfung mehrerer Argumente mit einem Leerzeichen. Wenn Sie nur das erste Argument zuschneiden und ausgeben möchten, verwenden Sie"$1"
stattdessenDas Skript:
Verwendungszweck:
Ausgabe:
quelle
[\ \t]
[[:space:]]
wie in einer der anderen Antworten verwenden: stackoverflow.com/a/3352015/3968618Sie können Old-School verwenden
tr
. Dies gibt beispielsweise die Anzahl der geänderten Dateien in einem Git-Repository zurück, wobei Leerzeichen entfernt wurden.quelle
Das hat bei mir funktioniert:
Um das für das gleiche Ergebnis in weniger Zeilen zu setzen:
quelle
${var##Pattern}
nach weiteren Details funktioniert . Außerdem werden auf dieser Website Bash-Muster erläutert . Die##
Mittel entfernen also das gegebene Muster von vorne und die%%
Mittel entfernen das gegebene Muster von hinten. Der+( )
Teil ist das Muster und bedeutet "ein oder mehrere Vorkommen eines Leerzeichens"ODER
ODER
ODER
ODER
Aufbauend auf Moskits Ausdruck ...
ODER
quelle
Ich habe gesehen, dass Skripte nur die Variablenzuweisung verwenden, um den Job zu erledigen:
Leerzeichen werden automatisch zusammengeführt und gekürzt. Man muss auf Schalenmetacharaktere achten (potentielles Injektionsrisiko).
Ich würde auch empfehlen, Variablensubstitutionen in Shell-Bedingungen immer doppelt in Anführungszeichen zu setzen:
da so etwas wie ein -o oder ein anderer Inhalt in der Variablen Ihre Testargumente ändern könnte.
quelle
$xyz
mitecho
der das Leerzeichen verschmilzt, nicht die Variablenzuweisung. Um den zugeschnittenen Wert in der Variablen in Ihrem Beispiel zu speichern, müssten Sie verwendenxyz=$(echo -n $xyz)
. Dieser Ansatz unterliegt auch einer potenziell unerwünschten Pfadnamenerweiterung (Globbing).xyz
Variablen wird NICHT getrimmt.quelle
echo $(echo "1 2 3")
(mit zwei Leerzeichen zwischen 1, 2 und 3).Ich würde einfach sed verwenden:
a) Anwendungsbeispiel für einzeilige Zeichenfolgen
Ausgabe:
b) Anwendungsbeispiel für mehrzeilige Zeichenfolgen
Ausgabe:
c) Schlussbemerkung:
Wenn Sie keine Funktion verwenden möchten, können Sie für einzeilige Zeichenfolgen einfach einen Befehl verwenden, der leichter zu merken ist:
Beispiel:
Ausgabe:
Die Verwendung der obigen Anweisungen für mehrzeilige Zeichenfolgen funktioniert ebenfalls , aber bitte beachten Sie, dass dadurch auch alle nachfolgenden / führenden internen Mehrfachbereiche abgeschnitten werden, wie GuruM in den Kommentaren bemerkt hat
Ausgabe:
Wenn es Ihnen etwas ausmacht, diese Leerzeichen beizubehalten, verwenden Sie bitte die Funktion am Anfang meiner Antwort!
d) ERLÄUTERUNG der sed-Syntax "find and replace" für mehrzeilige Zeichenfolgen, die innerhalb der Funktionsanpassung verwendet werden:
quelle
Hier ist eine trim () -Funktion, die Leerzeichen trimmt und normalisiert
Und eine andere Variante, die reguläre Ausdrücke verwendet.
quelle
*
Zeichen in der Eingabezeichenfolge verwendet wird Erweitern Sie auf alle Dateien und Ordner im aktuellen Arbeitsordner. Wenn $ IFS auf einen nicht standardmäßigen Wert eingestellt ist, funktioniert das Trimmen möglicherweise nicht (obwohl dies durch Hinzufügen leicht behoben werden kannlocal IFS=$' \t\n'
). Das Zuschneiden ist auf die folgenden Formen von Leerzeichen beschränkt: Leerzeichen\t
und\n
Zeichen.if
Leitung durch :if [[ "$trimmed" =~ ' '*([^ ]|[^ ].*[^ ])' '* ]]
. Schließlich befasst sich der Ansatz nur mit Leerzeichen, nicht mit anderen Formen von Leerzeichen (siehe meinen nächsten Kommentar).if
Zeile durch:[[ "$trimmed" =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]
Verwenden Sie AWK:
quelle
$stripped_version=
echo $ var | awk '{gsub (/ ^ + | + $ /, "")} 1'``Zuweisungen ignorieren führende und nachfolgende Leerzeichen und können als solche zum Trimmen verwendet werden:
quelle
echo "$var"
den Wert mit Leerzeichen aus.var=$(echo $var)
aber ich empfehle es nicht. Andere hier vorgestellte Lösungen sind bevorzugt.Dies hat nicht das Problem mit unerwünschtem Globbing, außerdem ist der innere Leerraum unverändert (vorausgesetzt, er
$IFS
ist auf den Standardwert eingestellt)' \t\n'
).Es liest bis zur ersten neuen Zeile (und enthält sie nicht) oder bis zum Ende der Zeichenfolge, je nachdem, was zuerst eintritt, und entfernt jede Mischung aus führenden und nachfolgenden Leerzeichen und
\t
Zeichen. Wenn Sie mehrere Zeilen beibehalten möchten (und auch führende und nachfolgende Zeilenumbrüche entfernen möchten), verwenden Sieread -r -d '' var << eof
stattdessen. Beachten Sie jedoch, dass Ihre Eingabe\neof
kurz zuvor abgeschnitten wird, wenn sie etwas enthält. (Andere Formen des weißen Raumes, nämlich\r
,\f
und\v
werden nicht entfernt werden , auch wenn Sie sie zu $ IFS hinzufügen.)quelle
Geben Sie Folgendes ein, um Leerzeichen und Tabulatoren vom linken zum ersten Wort zu entfernen:
cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html
quelle
Dadurch werden alle Leerzeichen aus Ihrem String entfernt.
/
Ersetzt das erste Vorkommen und//
alle Vorkommen von Leerzeichen in der Zeichenfolge. Dh alle Leerzeichen werden ersetzt durch - nichtsquelle
Dies ist die einfachste Methode, die ich je gesehen habe. Es wird nur Bash verwendet, es sind nur wenige Zeilen, der reguläre Ausdruck ist einfach und es entspricht allen Formen von Leerzeichen:
Hier ist ein Beispielskript zum Testen:
quelle
^[[:space:]]*(.*[^[:space:]])?[[:space:]]*$
Python hat eine Funktion
strip()
, die identisch mit PHPs funktionierttrim()
, daher können wir nur ein wenig Inline-Python ausführen, um ein leicht verständliches Dienstprogramm dafür zu erstellen:Dadurch werden führende und nachfolgende Leerzeichen (einschließlich Zeilenumbrüche) gekürzt.
quelle
quelle
Ich stellte fest, dass ich Code aus einer unordentlichen
sdiff
Ausgabe hinzufügen musste, um ihn zu bereinigen:Dadurch werden die nachgestellten Leerzeichen und andere unsichtbare Zeichen entfernt.
quelle
Leerzeichen in ein Leerzeichen entfernen:
quelle