$ Değişkenini bir dizinin kabuk destek genişlemesinde nasıl kullanabilirim?


33

$var inBir aralıkta bir basamaklama ile bir kabuk destek genişletme kullanmak istiyorum . Basitçe {$var1..$var2}söylemek işe yaramıyor, ben de "lateral" oldum ...

Aşağıdaki çalışıyor, ama biraz kludgey.

# remove the split files
echo rm foo.{$ext0..$extN} rm-segments > rm-segments
source rm-segments

Daha "normal" bir yol var mı?

Yanıtlar:


26

Denemek isteyebilirsiniz:

eval rm foo.{$ext0..$extN}

Bunun en iyi cevap olup olmadığından emin değilim, ama kesinlikle bir cevap.


Durrh! :( Açık göremedim ... Teşekkürler :)
Peter.O

4
Bash, {} genişleme $ genişlemeden önce gerçekleşir, bu yüzden, ifadeyi iki geçişe neden olmak için eval veya başka bir numara kullanmaktan başka bir yol olduğunu düşünmüyorum.
mattdm

6
Sadece! ... Orada "var" hayır ayracı genişleme ile {$one..$three}, bu durumda tamsayılar beklediğini ayracı-genişleme, geçerli bir biçimi değildir, çünkü sadece $ var genişletmeden sonra geçerli bir formu haline gelir ... daha evalsonra normal bir ayraç dizisi genişlemesi oluşturmak için aynı süreçten geçer ... 1 2 3 QED;) ... Özet: bir ayraç çiftinin basit varlığı ayraç genişlemesini tetiklemez ... yalnızca geçerli bir form tetikler .
Peter.O

@fred: Welcome :-)
asoundmove

Benzer bir değişken kullanırken a={0..9}; echo $a;, ayraç uzantısı yoktur . Kullanarak evalçalışır. Bu yüzden @ mattdm'in açıklaması iyi.
dr0i

20

Daha önce fark ettiğiniz gibi, {1..3}küme genişlemesine genişler 1 2 3ancak tetik olmaz {foo..bar}veya {$foo..$bar}ikincisi daha sonra yerine $foove $bardeğerleri ile genişletilir .

GNU'daki bir geri dönüş (örneğin gömülü olmayan Linux) seqkomuttur.

for x in `seq $ext0 $extN`; do rm foo.$x; done

Başka bir olasılık. eğer foo.hiçbir kabuk özel karakter içeriyor olduğu

rm `seq $ext0 $extN | sed 's/^/foo./'`

En basit çözüm, rm foo.{$ext0..$extN}istediğinizi nerede yapmak istediğini zsh kullanmaktır .


Seçenekler için teşekkürler. Hepsini gruplandırmış görmek güzel .. bash ve eval ile bağlı kalacağım ... eval şimdi sahnelerin arkasında neler olduğunu bildiğim kadar basit; bu yüzden artık bir sorun değil. Sürücü nedeniyle iyi bir atı değiştirmenize gerek yok
:)

1

Diğer cevaplar evalve komutlarını kullanarak tartışırken seq, aritmetik bağlamda bashgeleneksel bir C stili fordöngü kullanabilirsiniz . Değişkenler ext0ve döngünün tanımlanan aralık için çalışmasına neden olacak extNşekilde genişletilir ((..)).

for (( idx = ext0; idx <= extN; idx++ )); do
    [[ -f "$foo.$idx" ]] || { printf "file %s does not exist" "$foo.$idx" >&2 ; continue }
    rm "$foo.$idx"
done

En uygun yolu arıyorsanız ve birden çok rmkomuttan kaçınırsanız , dosya adı sonuçlarını saklamak ve rmtek seferde çağrı yapmak için geçici bir yer tutucu kullanabilirsiniz .

 results=()
 for (( idx = ext0; idx <= extN; idx++ )); do
     [[ -f "$foo.$idx" ]] || { printf "file %s does not exist" "$foo.$idx" >&2 ; continue }
     results+=( "$foo.$idx" )
 done

ve şimdi rmgenişletilmiş dizideki komutu çağırın

 rm -- "${results[@]}"

0
    function f_over_range {
        for i in $(eval echo {$1..$2}); do
            f $i
        done
    }

    function f {
        echo $1
    }

    f_over_range 0 5
    f_over_range 00 05

Notlar:

  • Eval kullanarak komut enjeksiyon güvenliği riski ortaya çıkarır
  • Linux "00 \ n01 \ n02..etc" yazacaktır ancak OSX "1 \ n2 \ n ... etc" yazacaktır.
  • Döngüler için seq veya C stili kullanmak, küme genişlemesinin baştaki sıfırları işlemesine uymaz
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.