मैं एक अनुक्रम के शेल ब्रेस विस्तार में $ चर का उपयोग कैसे कर सकता हूं?


33

मैं $var inएक सीमा के साथ शेल ब्रेस विस्तार का उपयोग करना चाहता हूं , बैश में। सीधे शब्दों में कहें {$var1..$var2}तो काम नहीं करता है, इसलिए मैं "पार्श्व" चला गया ...

निम्नलिखित काम करता है, लेकिन यह एक प्रकार का कुदाल है।

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

क्या अधिक "सामान्य" तरीका है?

जवाबों:


26

आप कोशिश कर सकते हैं:

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

यकीन नहीं है कि यह सबसे अच्छा जवाब है, लेकिन यह निश्चित रूप से एक है।


Durrh! :( मैं स्पष्ट नहीं देख सकता ... धन्यवाद :)
पीटर।

4
बाश में, {} विस्तार $ विस्तार से पहले होता है, इसलिए मुझे नहीं लगता कि अभिव्यक्ति के माध्यम से दो गुजरने के लिए eval या किसी अन्य चाल का उपयोग करने के अलावा ऐसा करने का कोई अन्य तरीका नहीं है।
Mattdm

6
मुझे सिर्फ "यह" मिला है! ... के साथ कोई ब्रेस विस्तार नहीं है{$one..$three} , क्योंकि यह ब्रेस-एक्सपेंशन का एक वैध रूप नहीं है, जो इस मामले में पूर्णांक की उम्मीद करता है ... यह केवल $ var विस्तार के बाद एक वैध रूप बन जाता है। जो evalतब सामान्य ब्रेस अनुक्रम विस्तार उत्पन्न करने के लिए उसी प्रक्रिया से गुजरता है ... 1 2 3 QED;) ... सारांश: ब्रेस पेयर की सरल उपस्थिति ब्रेस विस्तार को ट्रिगर नहीं करती है ... केवल एक वैध रूप इसे ट्रिगर करता है ।
पीटर।

@fred: स्वागत :-)
asoundmove

एक चर का उपयोग करते समय जैसे a={0..9}; echo $a;कोई ब्रेस एक्सटेंशन नहीं है । का उपयोग करते हुए eval, यह काम करता है। इसलिए मुझे लगता है कि @ mattdm की व्याख्या अच्छी है।
dr0i

20

आप पहले से ही महसूस किया के रूप में, {1..3}के लिए विस्तारित 1 2 3लेकिन {foo..bar}या {$foo..$bar}नहीं ट्रिगर ब्रेस विस्तार करते हैं, और बाद के बाद में बदलने के लिए विस्तार किया गया है $fooऔर $barउनके मूल्यों से।

जीएनयू (जैसे गैर-एम्बेडेड लिनक्स) पर एक गिरावट seqकमांड है।

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

एक अन्य संभावना। यदि foo.कोई शेल विशेष वर्ण नहीं है, है

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

सबसे सरल उपाय है rm foo.{$ext0..$extN}कि आप zsh का उपयोग करें, जहां आप चाहते हैं , वह कहां है।


विकल्पों के लिए धन्यवाद .. यह उन सभी को देखने के लिए अच्छा है .. मैं बैश और eval के साथ रहूँगा ... eval अभी काफी सरल है कि मुझे पता है कि पर्दे के पीछे क्या चल रहा है; तो यह अब कोई समस्या नहीं है। सवार की वजह से एक अच्छे घोड़े को बदलने की आवश्यकता नहीं है
:)

1

अन्य उत्तर का उपयोग कर के बारे में बात करते हुए evalऔर seqमें, bash, आप एक पारंपरिक सी शैली का उपयोग कर सकते forअंकगणितीय संदर्भ में पाश। चरों ext0और परिभाषित सीमा के लिए चलने के लिए लूप के extNअंदर विस्तार ((..))किया जाता है।

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

यदि आप एक इष्टतम तरीका ढूंढ रहे हैं और कई rmआदेशों से बचते हैं , तो आप फ़ाइलनाम परिणामों को संग्रहीत करने और rmएक-शॉट में कॉल करने के लिए एक अस्थायी प्लेसहोल्डर का उपयोग कर सकते हैं ।

 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

और अब rmविस्तारित सरणी पर कमांड को कॉल करें

 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

टिप्पणियाँ:

  • Eval का उपयोग कमांड इंजेक्शन सुरक्षा जोखिम को उजागर करता है
  • लिनक्स "00 \ n01 \ n02..etc" प्रिंट करेगा, लेकिन OSX "1 \ n2 \ _ ... आदि" प्रिंट करेगा
  • लूप के लिए सीक या सी-स्टाइल का उपयोग करना प्रमुख जीरो के ब्रेस विस्तार की हैंडलिंग से मेल नहीं खाएगा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.