Mam zmienną, która zawiera ciąg rozdzielany spacjami:
line="1 1.50 string"
Chcę podzielić ten ciąg ze spacją jako separator i zapisać wynik w tablicy, aby:
echo ${arr[0]}
echo ${arr[1]}
echo ${arr[2]}
wyjścia
1
1.50
string
Gdzieś znalazłem rozwiązanie, które nie działa:
arr=$(echo ${line})
Jeśli po tym uruchomię powyższe instrukcje echa, otrzymam:
1 1.50 string
[empty line]
[empty line]
Też próbowałem
IFS=" "
arr=$(echo ${line})
z tym samym wynikiem. Czy ktoś może pomóc?
set -f; arr=($string); set +f
wydaje się być szybszy niżread -r -a <<< $string
.Odpowiedzi:
Aby przekonwertować ciąg znaków na tablicę, użyj
lub
Ważne jest, aby nie używać cudzysłowów, ponieważ to załatwia sprawę.
źródło
for i in ${arr[@]}; do echo $i; done
echo ${arr[@]}
$line
zawierają znaki globowania.mkdir x && cd x && touch A B C && line="*" arr=($line); echo ${#arr[@]}
daje 3declare -a "arr=($line)"
zignorujeIFS
ograniczniki wewnątrz cytowanych ciągówline='*'
,read -a arr <<<$line
zawsze działa, ale tylkoarr=($line)
się nie powiedzie.Spróbuj tego:
źródło
line='*'
W:
arr=( $line )
. „Podział” kojarzy się z „glob”.Symbole wieloznaczne (
*
,?
i[]
) zostaną rozwinięte do pasujących nazw plików.Prawidłowe rozwiązanie jest tylko nieco bardziej złożone:
Nie ma problemu z globowaniem; znak podziału jest ustawiony
$IFS
, cytowane zmienne.źródło
arr=($line)
w przyjętej odpowiedzi cierpi z powodu problemów globowania. Na przykład, spróbuj:line="twinkling *"; arr=($line); declare -p arr
.<<<
ale dobrym pomysłem może być nadal stosowanie podwójnych cudzysłowów dla zachowania spójności i czytelności.Jeśli potrzebujesz rozszerzenia parametrów, spróbuj:
Na przykład weź następujący kod.
Jeśli bieżący katalog zawiera pliki
a.txt
,b.txt
ac.txt
następnie wykonanie kodu wygeneruje następujące dane wyjściowe.źródło
źródło
tr
Pętla jest nieprawidłowa, dobrze dzieli tablicę, a rura jest zbędna, ale"${arr[@]}"
zamiast tego powinna się zapętlić , nie$arr