तत्वों को zsh में रिक्त स्थान के साथ सूचीबद्ध करें


10

मैं इस बिंदु पर सभी 2 घंटे के लिए zsh स्क्रिप्टिंग का अध्ययन कर रहा हूं और मैंने एक दीवार को मारा है। मैं उन फाइलों की एक सूची से गुजरना चाहता हूं जिनमें उनके स्थान हो सकते हैं। मैं निम्नलिखित उदाहरण की तुलना में पूरी तरह से अलग दृष्टिकोणों के लिए खुला हूं जब तक कि वे zsh के बाद से zsh हैं जो मैं पढ़ रहा हूं, वह कार्य नहीं जो मैं स्क्रिप्ट की कोशिश कर रहा हूं।

files=(`ls`)
for f in $files; do
    print $f
done

मैं स्पष्ट रूप से सिर्फ मनोरंजन नहीं कर रहा हूं ls, मैं बस $fलूप के प्रत्येक पुनरावृत्ति को पूरी फ़ाइल नाम पर कब्जा करना चाहता हूं ।

जवाबों:


12

सबसे पहले, मैं मानता हूं कि इसका उपयोग lsकेवल एक उदाहरण है। आप lsकिसी भी शेल के आउटपुट को पार्स नहीं कर सकते , क्योंकि यह अस्पष्ट है। पढ़ें कि अगर आपको यह खबर है तो आपको ls (1) के आउटपुट को पार्स नहीं करना चाहिए । किसी भी शेल में, फ़ाइलों की सूची प्राप्त करने के लिए, वाइल्डकार्ड्स का उपयोग करें, जैसे files=(*)

Zsh में, अन्य गोले की तरह, कमांड प्रतिस्थापन का परिणाम व्हॉट्सएप वर्णों में शब्दों में विभाजित होता है (अधिक सटीक रूप से, मूल्य के अनुसार IFS)। (अन्य गोले के विपरीत, कमांड प्रतिस्थापन का परिणाम zsh में ग्लोबिंग के अधीन नहीं है।) इसलिए यदि lsकमांड का आउटपुट है

hello world
wibble

तो files=($(ls))सेट filesसरणी 3 तत्वों को रोकने के: hello, worldऔर wibble

यदि कमांड प्रतिस्थापन डबल कोट्स में है, तो कोई विभाजन नहीं किया जाता है। आप पैरामीटर विस्तार झंडे के साथ कस्टम विभाजन कर सकते हैं । @ध्वज का उपयोग यह इंगित करने के लिए करें कि विभाजन का परिणाम एक सरणी है (अजीब तरह से, आपको दोहरे उद्धरणों में विस्तार को रखने की आवश्यकता है, अर्थात "${(@)…}", भले ही दोहरे उद्धरण वाला स्ट्रिंग कई शब्दों तक विस्तारित हो जाएगा)। विभाजन के लिए, sध्वज का उपयोग करें , उदाहरण के "${(@s:,:)…}"लिए अल्पविराम में विभाजित करने के लिए; fझंडा केवल नई-पंक्तियों में विभाजित होता है।

files=("${(@f)$(ls)}")

ध्यान दें कि सामान्य for f in $files[@]रूप से एक सरणी पर पुनरावृति करने का उचित तरीका है , क्योंकि $filesखाली तत्वों से स्ट्रिप्स (यहां, यह कोई फर्क नहीं पड़ता क्योंकि तत्व खाली नहीं होंगे)।

print $f$fएक स्विच के रूप में व्याख्या करता है अगर यह एक के साथ शुरू होता है -और बैकस्लैश का विस्तार करता है $f। उपयोग करें print -r -- $f, या print -rn -- $fयदि आप स्ट्रिंग के बाद एक नई पंक्ति नहीं जोड़ना चाहते हैं।


धन्यवाद। हां, ls सिर्फ एक उदाहरण था। इस समय दिमाग में कोई खास लक्ष्य नहीं था, मैं सिर्फ यह जानना चाहता हूं कि किसी भी कमांड से सूची तत्वों को कैसे उद्धृत या बचाना है, जिसमें उनके सफेद स्थान के साथ व्यक्तिगत परिणाम हो सकते हैं।
फेलिक्स

एक बात जो मुझे भ्रामक लगती है वह यह है कि आपकी फाइलों में बाहरी () = ("$ {(@ f) $ (ls)}") @f के साथ अभिव्यक्ति आवश्यक है? और बस (चारों ओर) खेलते हुए तब तक ठीक काम करना प्रतीत होता है जब तक (बाहर) दिखाई देता है।
कोबोज

@Koobz 1. बाहरी (…)आवश्यक है ताकि filesएक सरणी हो और न कि एक स्ट्रिंग (जिसमें कमांड से लाइनों का संघनन होगा, द्वारा किए गए विभाजन को पूर्ववत करें (f))। 2. foo=$'one\n\nthree', contrast प्रिंट के साथ-$ $ {(f) foo} `और print "${(@f)foo}"। खाली लाइनों को बनाए रखने के लिए दोहरे उद्धरण चिह्नों की आवश्यकता होती है, जो आपको नहीं मिलेंगे, lsलेकिन अन्य कमांड के साथ हो सकते हैं।
गिल्स एसओ- बुराई को रोकना '26

बहुत सराहना की। क्या इस पागलपन का कोई तुक या तर्क है? यहां तक ​​कि, जो भ्रामक है वह यह है कि बाहरी () सिर्फ व्यक्तिगत शब्दों पर स्ट्रिंग को फिर से विभाजित क्यों नहीं करता है यदि मध्यवर्ती मूल्य मेरा संक्षिप्त स्ट्रिंग है। यह उदाहरण के लिए रूबी या php में स्ट्रिंग प्रक्षेप जैसा दिखता है।
कोबोज़

@Koobz खाली शब्दों के विशेष उपचार का कारण लंबे समय से भूले हुए पुराने संस्करणों के साथ ऐतिहासिक अनुकूलता है। स्वचालित रूप से विभाजित न होने का कारण यह है कि यह एक आश्चर्यजनक और अक्सर वांछनीय व्यवहार नहीं है। स्वचालित विभाजन बॉर्न शेल का एक व्यवहार है जो zsh का अनुकरण नहीं करता है जब तक कि आप इसे नहीं बताते हैं।
गिल्स एसओ- बुराई को रोकना '

2

Zsh में आप शेल के विस्तार का उपयोग कर सकते हैं जो डिफ़ॉल्ट रूप से शब्द विभाजन नहीं करता है। प्रयत्न

for f in /path/to/files/*; do
    print ${f}
done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.