यदि आप बैश संस्करण 4 या उससे ऊपर (जो कि लिनक्स के किसी भी आधुनिक संस्करण में होना चाहिए) चला रहे हैं, तो आप मूल सरणी के प्रत्येक मान वाले एक नए साहचर्य सरणी को बनाकर बैश में अद्वितीय सरणी मान प्राप्त कर सकते हैं। कुछ इस तरह:
$ a=(aa ac aa ad "ac ad")
$ declare -A b
$ for i in "${a[@]}"; do b["$i"]=1; done
$ printf '%s\n' "${!b[@]}"
ac ad
ac
aa
ad
यह काम करता है क्योंकि किसी भी एरे (किसी भाषा में सहयोगी या पारंपरिक) में, प्रत्येक कुंजी केवल एक बार दिखाई दे सकती है। जब for
लूप के दूसरे मूल्य पर आता aa
है a[2]
, तो यह ओवरराइट करता है b[aa]
जो मूल रूप से इसके लिए सेट किया गया था a[0]
।
देशी बैश में चीजें करना पाइप और बाहरी उपकरणों का उपयोग करने की तुलना में तेज हो सकता है sort
और uniq
, हालांकि बड़े डेटासेट के लिए आप बेहतर प्रदर्शन देखेंगे यदि आप अधिक शक्तिशाली भाषा जैसे कि awk, python, आदि का उपयोग करते हैं।
यदि आप आश्वस्त महसूस कर रहे हैं, तो आप कई तर्कों के लिए अपने प्रारूप को रीसायकल करने की क्षमता for
का उपयोग करके लूप से बच सकते हैं printf
, हालांकि इसके लिए आवश्यकता होती है eval
। (यदि आप इसके साथ ठीक हैं तो अभी पढ़ना बंद कर दें।)
$ eval b=( $(printf ' ["%s"]=1' "${a[@]}") )
$ declare -p b
declare -A b=(["ac ad"]="1" [ac]="1" [aa]="1" [ad]="1" )
इस समाधान की आवश्यकता eval
है कि शब्द बंटवारे से पहले सरणी मान निर्धारित किए जाते हैं। इसका मतलब है कि कमांड प्रतिस्थापन का आउटपुट कुंजी = मान जोड़े के एक सेट के बजाय एक शब्द माना जाता है ।
हालांकि यह एक सबशेल का उपयोग करता है, यह सरणी मान को संसाधित करने के लिए केवल बैश बिल्डिंस का उपयोग करता है। eval
आलोचनात्मक नज़र से अपने उपयोग का मूल्यांकन करना सुनिश्चित करें । यदि आप 100% आश्वस्त नहीं हैं कि चेपर या ग्लेन जैकमैन या ग्रीकाट को आपके कोड के साथ कोई गलती नहीं मिलेगी, तो लूप के बजाय उपयोग करें।
uniq=($(printf "%s\n" "${ids[@]}" | sort -u)); echo "${uniq[@]}"