Odpowiedzi:
Awk to dobra opcja, jeśli masz do czynienia z końcowymi białymi spacjami, ponieważ zajmie się tym za Ciebie:
echo " word1 word2 " | awk '{print $1;}' # Prints "word1"
Cut nie zajmie się tym jednak:
echo " word1 word2 " | cut -f 1 -d " " # Prints nothing/whitespace
„Wytnij” tutaj nie drukuje nic / białych znaków, ponieważ pierwszą rzeczą przed spacją była kolejna spacja.
-F","
do zastąpienia domyślnego separatora pól (spacji) przecinkiem.
nie ma potrzeby używania poleceń zewnętrznych. Sam Bash może wykonać zadanie. Zakładając, że „słowo1 słowo2” skądś pobrałeś i zapisałeś w zmiennej np
$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2
teraz możesz przypisać $ 1 lub $ 2 itd. do innej zmiennej, jeśli chcesz.
stdin
. @Matt M. --
oznacza stdin
, że $string
jest przekazywany jako stdin
. stdin
jest oddzielone białymi znakami na argumenty $1
, $2
, $3
, itd. - tak jak wtedy, gdy bash wartościowanie programu argumenty (np czek $1
, $2
itd), to podejście wykorzystuje skłonność powłoki o podziale stdin
automatycznie do argumentów, usuwając potrzebę awk
lub cut
.
set
ustawia argumenty powłoki.
word1=$(IFS=" " ; set -- $string ; echo $1)
Ustaw IFS, aby poprawnie rozpoznawał odstępy między wyrazami. Zawiń w nawiasy, aby uniknąć wybicia oryginalnej zawartości 1 USD.
string="*"
. Niespodzianka.
Myślę, że skutecznym sposobem jest użycie tablic bash:
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
Możesz także bezpośrednio czytać tablice w rurociągu:
echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done
echo " word1 word2 " | { read -a array ; echo ${array[0]} ; }
string="*"
. Niespodzianka.
while
składni, aby pobrać każde pierwsze słowo w każdym wierszu. W przeciwnym razie użyj podejścia Boontawee Home. Należy również pamiętać, że echo "${array[0]}"
zostało zacytowane, aby zapobiec ekspansji, jak zauważył gniourf-gniourf.
echo "word1 word2 word3" | { read first rest ; echo $first ; }
Ma to tę zaletę, że nie używa zewnętrznych poleceń i pozostawia zmienne $ 1, $ 2 itd. Nienaruszone.
$1, $2, …
nienaruszonych jest niezwykle przydatną funkcją przy pisaniu skryptów!
Jeśli jesteś pewien, że nie ma spacji wiodących, możesz użyć podstawiania parametrów bash:
$ string="word1 word2"
$ echo ${string/%\ */}
word1
Uważaj na ucieczkę z pojedynczej przestrzeni. Zobacz tutaj, aby uzyskać więcej przykładów wzorców zastępowania. Jeśli masz bash> 3.0, możesz również użyć dopasowywania wyrażeń regularnych, aby poradzić sobie ze spacjami wiodącymi - zobacz tutaj :
$ string=" word1 word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
%% *
Oto inne rozwiązanie wykorzystujące rozszerzenie parametrów powłoki . Dba o wiele spacji po pierwszym słowie. Obsługa spacji przed pierwszym słowem wymaga jednego dodatkowego rozszerzenia.
string='word1 word2'
echo ${string%% *}
word1
string='word1 word2 '
echo ${string%% *}
word1
W %%
oznacza usuwanie najdłuższy mecz *
(spację dowolnej liczby dowolnych innych znaków) w tylnej części string
.
Zastanawiałem się, jak kilka najpopularniejszych odpowiedzi wypada pod względem szybkości. Przetestowałem:
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]} ; }
i 4 @ boontawee-home's
echo "..." | { read first _ ; echo $first ; }
Zmierzyłem je za pomocą czasu Pythona w skrypcie Bash w terminalu Zsh na macOS, używając ciągu testowego z 215 5-literowymi słowami. Wykonałem każdy pomiar pięć razy (wszystkie wyniki obejmowały 100 pętli, najlepszy z 3) i uśredniono wyniki:
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")
Dobra robota, wyborcy 👏 Głosy (w chwili pisania tego tekstu) odpowiadają szybkości rozwiązań!
read -a
jest nieprawidłowy w myślniku).
echo "word1 word2" | cut -f 1 -d " "
cut wycina pierwsze pole (-f 1) z listy pól rozdzielonych ciągiem znaków "" (-d "")
read
jest twoim przyjacielem:
Jeśli ciąg jest w zmiennej:
string="word1 word2"
read -r first _ <<< "$string"
printf '%s\n' "$first"
Jeśli pracujesz w potoku: pierwszy przypadek: chcesz tylko pierwszego słowa z pierwszego wiersza:
printf '%s\n' "word1 word2" "line2" | { read -r first _; printf '%s\n' "$first"; }
drugi przypadek: chcesz, aby pierwsze słowo w każdym wierszu:
printf '%s\n' "word1 word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done
Działają, jeśli istnieją spacje wiodące:
printf '%s\n' " word1 word2" | { read -r first _; printf '%s\n' "$first"; }
Pracowałem z urządzeniem wbudowanym, które nie miało ani Perla, awk, ani Pythona i zamiast tego zrobiłem to z sedem. Obsługuje wiele spacji przed pierwszym słowem (których rozwiązania cut
i bash
nie obsłużyły).
VARIABLE=" first_word_with_spaces_before_and_after another_word "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'
Było to bardzo przydatne podczas grepowania ps
dla identyfikatorów procesów, ponieważ inne rozwiązania tutaj używające tylko basha nie były w stanie usunąć pierwszych spacji ps
używanych do wyrównania.