मजबूती से पथ निर्माण


16

कहो कि मेरे पास एक शेल स्क्रिप्ट में कई चर हैं (जैसे zsh में):

FOLDER_1, FOLDER_2, etc.

ये चरों से आने वाले फ़ोल्डरों को संदर्भित करते हैं /। उदाहरण के लिए, यदि मेरे पास एक रास्ता है/home/me/stuff/items

चर होंगे:

FOLDER_1='home'
FOLDER_2='me'
FOLDER_3='stuff'

अब, यह कहें कि मैं चर को समेटकर संबंधित पथ को वापस बनाना चाहता हूं। एक संभव तरीका निम्नानुसार पथ का निर्माण करना है:

PATH=$FOLDER_1/$FOLDER_2/$FOLDER_3/

हालाँकि, कहते हैं कि कुछ वैरिएबल FOLDER_iआगे की स्लैश के साथ आते हैं, जबकि अन्य नहीं करते हैं (और हमें नहीं पता है) जैसे

FOLDER_1='home'
FOLDER_2='stuff/'
FOLDER_3='items'

मेरा सवाल है: मैं कैसे मजबूत तरीके से पथ का निर्माण कर सकता हूं?(जैसे डबल स्लैश से बचना, और उन्हें जोड़ना जहाँ उन्हें होना चाहिए)।

मैंने सोचा कि ऐसा करने का एक तरीका /हमेशा चर के जोड़े के बीच जोड़ना है , और उसके बाद किसी भी डुप्लिकेट को हटा दें sed, लेकिन मैं इसे काम नहीं कर सकता (मुझे यकीन नहीं है कि मैं /सही तरीके से संभाल रहा हूंsed )।

इसके अलावा, क्या मैं पहिया को सुदृढ़ कर रहा हूं ? (यानी वहाँ कोई अंतर्निहित है कि यह पहले से ही है?)।

अंतिम रूप से, यदि चर एक सरणी में हैं , उदाहरण के लिए FOLDERS, क्या बिना लूपिंग के ऐसा करना संभव होगा? (या वैकल्पिक रूप से, लूपिंग द्वारा लेकिन यह जाने बिना कि FOLDERSसरणी में कितने हैं)।

जवाबों:


12

आप printfएक सरणी के साथ उपयोग कर सकते हैं :

parts=("$FOLDER_1" "$FOLDER_2" "$FOLDER_3");
printf '/%s' "${parts[@]%/}"
# Use "printf -v path" to save it into a variable called "path" instead of printing it

%ऑपरेटर तार अनुगामी, इस मामले में ट्रिम /। इसे लगाने सेparts[@] , यह प्रत्येक सरणी सदस्य को अलग से ट्रिम करता है।

इस printfट्रिक को समझने की कुंजी यह है man 1 printf: "प्रारूप स्ट्रिंग को तर्कों को संतुष्ट करने के लिए जितनी बार आवश्यक हो पुन: उपयोग किया जाता है।"


सिंगल %मेथड के लिए एकल पद्धति काम करती है जिसका उल्लेख है। जब कई स्लैश होते हैं, तो ${parts[@]%%/*}काम पूरा करने के लिए । यहाँ स्लैश मुद्दे पर थोड़ी और जानकारी के लिए एक लिंक दिया गया है: UNIX पथ में डबल स्लैश का क्या अर्थ है? क्या 'cd dir / subdir // वैध है ...
पीटर.ऑक्ट

2
@ संदर्भित: /*इस मामले में शून्य या अधिक स्लैश का मतलब नहीं है , बल्कि किसी भी वर्ण द्वारा पीछा किया जाने वाला स्लैश है। इसका मतलब है कि यदि आपका रास्ता स्लैश से शुरू होता है, तो परिणाम खाली स्ट्रिंग होगा!
lbb0

मैंने उदाहरण के अनुसार, माना था कि केवल स्लैशिंग स्लैश होंगे। हालांकि, एक प्रमुख स्लैश (एस) की संभावना के अनुकूल होने के लिए, बैश के extglob(रेगेक्स के साथ) का उपयोग किया जा सकता है shopt -s extglob; ${parts[@]%%/+(/)}...
पीटर।

15

सरल उत्तर है कि चिंता करना बंद करो और कई स्लैशों को प्यार करो। मल्टीपल स्लैश का एकल स्लैश के समान प्रभाव होता है (सिवाय इसके कि एक शुरुआत के साथ //कुछ तरीकों पर एक अलग अर्थ होता है, विंडोज पर यूनिक्स अनुकरण परतें केवल वही हैं जिन्हें मैं नाम दे सकता हूं)। यह डिज़ाइन द्वारा है, और कई स्लैश के बारे में चिंता किए बिना फ़ाइल नामों को इकट्ठा करने में सक्षम होने के कारण उस डिज़ाइन निर्णय का एक प्रमुख हिस्सा था।

सरणी तत्वों में शामिल होने के लिए, zsh में, आप j पैरामीटर विस्तार ध्वज का उपयोग कर सकते हैं ।

dir=${(j:/:)FOLDERS}

आप डुप्लिकेट स्लैश को स्क्वीज़ कर सकते हैं, जबकि आप इस पर हैं, लेकिन यह विशुद्ध रूप से कॉस्मेटिक है।

setopt extended_glob
dir=${${(j:/:)FOLDERS}//\/\/##/\/}

Ksh और bash में, आप $IFSविभाजक के रूप में पहले वर्ण का उपयोग करके एक सरणी में शामिल हो सकते हैं । फिर आप डुप्लिकेट स्लैश स्क्वैश कर सकते हैं। बैश में, आपको shopt -s extglobनीचे स्निपेट की अंतिम पंक्ति में ksh ग्लब्स को सक्षम करने की आवश्यकता होगी ।

IFS=/
dir="${FOLDERS[*]}"
unset IFS
dir=${dir//\/+(\/)//}

3

आपके लिए कैसे sedकाम नहीं कर रहा है? कंक्रीटिंग के sed 's|/\+|/|g'बाद या sed 's|/||g'पहले प्रयास करें ।


1

bash 4विस्तारित ग्लोबिंग की शुरुआत की, जो नियमित रूप से पैरामीटर प्रतिस्थापन में मिलान करने में सक्षम बनाता है ${var....}... यह डिफ़ॉल्ट रूप से बंद है। अपनी स्क्रिप्ट के लिए इसे सक्षम करने के लिए, बस खोल विकल्प सेट extglob ...

उस $ दिर = मानकर/home/me/////////stuff//items

shopt -s extglob; dir="${dir//+(\/)//}"

$ Dir का परिणामी मूल्य

/home/me/stuff/items  

यहाँ कुछ उदाहरण हैं- do-s-and-s- Bash Extended Globbing

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.