Bash içindeki bir diziye ayrılmış bir dize okuma


206

Alan sınırlı bir dize içeren bir değişken var:

line="1 1.50 string"

Bu dizeyi boşlukla ayırıcı olarak bölmek ve sonucu bir dizide saklamak istiyorum, böylece:

echo ${arr[0]}
echo ${arr[1]}
echo ${arr[2]}

çıktılar

1
1.50
string

Bir yerde işe yaramayan bir çözüm buldum:

arr=$(echo ${line})

Bundan sonra yankı ifadelerini çalıştırırsam, şunu elde ederim:

1 1.50 string
[empty line]
[empty line]

Ben de denedim

IFS=" "
arr=$(echo ${line})

aynı sonucu verir. Birisi yardım edebilir mi lütfen?


Unix & Linux Stack Exchange ile ilgili bu cevaba bakınız: Herestring ile sed kullanma (<<<) ve okuma -a . set -f; arr=($string); set +fdaha hızlı görünüyor read -r -a <<< $string.
codeforester

Yanıtlar:


331

Bir dizeyi diziye dönüştürmek için lütfen

arr=($line)

veya

read -a arr <<< $line

Hile yapmak için tırnak işareti kullanmamak çok önemlidir.


7
ve güzel yeni dizinizin akıl sağlığını kontrol etmek için:for i in ${arr[@]}; do echo $i; done
Banjer

5
ya da sadeceecho ${arr[@]}
Banjer

13
$lineİçinde globbing karakterler varsa her iki yol da başarısız olabilir . mkdir x && cd x && touch A B C && line="*" arr=($line); echo ${#arr[@]}3 verir
Tino

3
declare -a "arr=($line)"IFSalıntılanan dizeler içindeki sınırlayıcıları yok sayacak
Dave

4
@Tino Hayır. Ne zaman line='*', read -a arr <<<$lineher zaman çalışır, ama sadece arr=($line)başarısız olur.
Johnny Wong

39

Bunu dene:

arr=(`echo ${line}`);

5
Güzel - Bu çözüm, yukarıdaki diğer yaklaşımların bazılarının başarısız olduğu Z kabuğunda da çalışır.
Keith Hughitt

Bu işe yarıyor, neden işe yaradığını açıklayabilir misiniz?
smartwjw

2
Açıklama: Bu, satırda '*' olduğunda da işe yaramaz, örneğinline='*'
Johnny Wong

34

In: arr=( $line ). "Split", "glob" ile ilişkilendirilir.
Joker karakterler ( *, ?ve []) eşleşen dosya adlarına genişletilir.

Doğru çözüm sadece biraz daha karmaşıktır:

IFS=' ' read -a arr <<< "$line"

Globbing problemi yok; bölünmüş karakter $IFS, değişkenler alıntılanır.


5
Bu kabul edilen cevap olmalı. İfadesi arr=($line)de kabul cevap globbing konulardan muzdarip. Örneğin, deneyin: line="twinkling *"; arr=($line); declare -p arr.
codeforester

Alıntılama, yorumlama için isteğe bağlıdır, <<<ancak tutarlılık ve okunabilirlik için yine de çift tırnak kullanmak iyi bir fikir olabilir.
codeforester

6

Parametre genişletmeye ihtiyacınız varsa, şunu deneyin:

eval "arr=($line)"

Örneğin, aşağıdaki kodu alın.

line='a b "c d" "*" *'
eval "arr=($line)"
for s in "${arr[@]}"; do 
    echo "$s"
done

Eğer geçerli dizin dosyalar var a.txt, b.txtve c.txtsonra aşağıdaki çıktıyı üretecektir kodunu yürütmeden.

a
b
c d
*
a.txt
b.txt
c.txt

-9
line="1 1.50 string"

arr=$( $line | tr " " "\n")

for x in $arr
do
echo "> [$x]"
done

Döngü yanlış, dizi ince böler ve boru içine trgereksiz ama bunun "${arr[@]}"yerine döngü gerekir , değil$arr
Zorf
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.