Antworten:
Awk ist eine gute Option, wenn Sie sich mit nachgestellten Leerzeichen befassen müssen, da dies für Sie erledigt wird:
echo " word1 word2 " | awk '{print $1;}' # Prints "word1"
Cut kümmert sich aber nicht darum:
echo " word1 word2 " | cut -f 1 -d " " # Prints nothing/whitespace
'cut' hier druckt nichts / Leerzeichen, weil das erste, was vor einem Leerzeichen stand, ein anderes Leerzeichen war.
-F","
das Standardfeldtrennzeichen (ein Leerzeichen) mit einem Komma überschreiben.
Es müssen keine externen Befehle verwendet werden. Bash selbst kann den Job machen. Angenommen, "word1 word2" stammt von irgendwoher und ist in einer Variablen gespeichert, z
$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2
Jetzt können Sie einer anderen Variablen $ 1 oder $ 2 usw. zuweisen, wenn Sie möchten.
stdin
. @Matt M. --
bedeutet stdin
, wird also $string
als übergeben stdin
. stdin
durch Leerzeichen getrennt in Argumente $1
, $2
, $3
usw. - so wie wenn ein heftiger Schlag Programm auswertet Argumente (zB Scheck $1
, $2
etc.), ist dieser Ansatz den Vorteil der Tendenz der Shell nimmt die aufzuspalten stdin
automatisch in Argumente, für die Beseitigung der Notwendigkeit awk
oder cut
.
set
legt die Shell-Argumente fest.
word1=$(IFS=" " ; set -- $string ; echo $1)
Stellen Sie IFS so ein, dass der Abstand zwischen den Wörtern korrekt erkannt wird. In Klammern setzen, um zu vermeiden, dass der ursprüngliche Inhalt von 1 US-Dollar beeinträchtigt wird.
string="*"
. Überraschung.
Ich denke, ein effizienter Weg ist die Verwendung von Bash-Arrays:
array=( $string ) # do not use quotes in order to allow word expansion
echo ${array[0]} # You can retrieve any word. Index runs from 0 to length-1
Sie können Arrays auch direkt in einer Pipeline lesen:
echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done
echo " word1 word2 " | { read -a array ; echo ${array[0]} ; }
string="*"
. Überraschung.
while
Syntax, um jedes erste Wort in jeder Zeile abzurufen. Verwenden Sie andernfalls den Boontawee Home-Ansatz. Bitte beachten Sie auch, dass echo "${array[0]}"
dies zitiert wurde, um eine von gniourf-gniourf festgestellte Erweiterung zu verhindern.
echo "word1 word2 word3" | { read first rest ; echo $first ; }
Dies hat den Vorteil, dass keine externen Befehle verwendet werden und die Variablen $ 1, $ 2 usw. intakt bleiben.
$1, $2, …
ist eine äußerst nützliche Funktion zum Schreiben von Skripten!
Wenn Sie sicher sind, dass keine führenden Leerzeichen vorhanden sind, können Sie die Bash-Parameterersetzung verwenden:
$ string="word1 word2"
$ echo ${string/%\ */}
word1
Achten Sie darauf, dass Sie dem einzelnen Raum entkommen. Sehen Sie hier für weitere Beispiele von Substitutionsmuster. Wenn Sie bash> 3.0 haben, können Sie auch die Übereinstimmung regulärer Ausdrücke verwenden, um mit führenden Leerzeichen umzugehen - siehe hier :
$ string=" word1 word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
%% *
Hier ist eine andere Lösung mit Shell-Parametererweiterung . Es kümmert sich um mehrere Leerzeichen nach dem ersten Wort. Die Behandlung von Leerzeichen vor dem ersten Wort erfordert eine zusätzliche Erweiterung.
string='word1 word2'
echo ${string%% *}
word1
string='word1 word2 '
echo ${string%% *}
word1
Die %%
bedeutet das Löschen die längste mögliche Übereinstimmung von *
(einem Raum , gefolgt von einer beliebigen Anzahl von was auch immer andere Zeichen) im hinteren Teil string
.
Ich fragte mich, wie viele der Top-Antworten in Bezug auf die Geschwindigkeit gemessen wurden. Ich habe folgendes getestet:
1 @ mattbh's
echo "..." | awk '{print $1;}'
2 @ ghostdog74's
string="..."; set -- $string; echo $1
3 @ boontawee-home's
echo "..." | { read -a array ; echo ${array[0]} ; }
und 4 @ boontawee-home's
echo "..." | { read first _ ; echo $first ; }
Ich habe sie mit Pythons Zeit in einem Bash-Skript in einem Zsh-Terminal unter macOS gemessen, wobei ich eine Testzeichenfolge mit 215 Wörtern aus 5 Buchstaben verwendet habe. Hat jede Messung fünfmal durchgeführt (die Ergebnisse waren alle für 100 Schleifen, am besten von 3) und hat die Ergebnisse gemittelt:
method time
--------------------------------
1. awk 9.2ms
2. set 11.6ms (1.26 * "1")
3. read -a 11.7ms (1.27 * "1")
4. read 13.6ms (1.48 * "1")
Gute Arbeit, Wähler 👏 Die Stimmen (zum Zeitpunkt dieses Schreibens) entsprechen der Geschwindigkeit der Lösungen!
read -a
ist in Bindestrich ungültig).
echo "word1 word2" | cut -f 1 -d " "
cut schneidet das 1. Feld (-f 1) aus einer Liste von Feldern ab, die durch die Zeichenfolge "" (-d "") begrenzt sind.
read
ist dein Freund:
Wenn sich die Zeichenfolge in einer Variablen befindet:
string="word1 word2"
read -r first _ <<< "$string"
printf '%s\n' "$first"
Wenn Sie in einer Pipe arbeiten: Erster Fall: Sie möchten nur das erste Wort der ersten Zeile:
printf '%s\n' "word1 word2" "line2" | { read -r first _; printf '%s\n' "$first"; }
Zweiter Fall: Sie möchten das erste Wort jeder Zeile:
printf '%s\n' "word1 word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done
Diese funktionieren, wenn es führende Räume gibt:
printf '%s\n' " word1 word2" | { read -r first _; printf '%s\n' "$first"; }
Ich habe mit einem eingebetteten Gerät gearbeitet, das weder Perl, Awk noch Python hatte, und es stattdessen mit sed gemacht. Es werden mehrere Leerzeichen vor dem ersten Wort unterstützt (die mit den cut
und bash
-Lösungen nicht behandelt wurden).
VARIABLE=" first_word_with_spaces_before_and_after another_word "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'
Dies war sehr nützlich, wenn ps
nach Prozess-IDs gesucht wurde , da die anderen Lösungen, die hier nur bash verwenden, die ersten Leerzeichen, die ps
zum Ausrichten verwendet werden, nicht entfernen konnten .