क्या बैश के साथ एक सरणी के अंतिम तत्व को पढ़ने का एक तरीका है?


68

अगर मेरे पास 5 तत्वों के साथ एक सरणी है, उदाहरण के लिए:

[a][b][c][d][e]

इसका उपयोग करके echo ${myarray[4]}मैं देख सकता हूँ कि यह क्या है।

लेकिन क्या होगा अगर मुझे दिए गए सरणी में तत्वों की संख्या पता नहीं है? क्या अज्ञात लंबाई सरणी के अंतिम तत्व को पढ़ने का एक तरीका है? किसी भी सरणी के लिए दाईं से बाईं ओर पढ़ने वाला पहला तत्व?

मैं यह जानना चाहूंगा कि यह कैसे करना है।


$@वास्तव में एक सरणी नहीं है (सबस्क्रिप्ट नहीं की जा सकती)। इसके लिए, शेल स्क्रिप्ट को अंतिम तर्क प्राप्त करना देखें ।
टॉम हेल

जवाबों:


89

आप अंतिम तत्व प्राप्त करने के लिए सिर्फ एक नकारात्मक सूचकांक ${myarray[-1]} का उपयोग कर सकते हैं । आप दूसरी-आखिरी चीज़ के लिए भी ऐसा ही कर सकते हैं; बैश में:

यदि किसी अनुक्रमणित सरणी के एक तत्व को संदर्भित करने के लिए उपयोग की जाने वाली सबस्क्रिप्ट शून्य से कम संख्या का मूल्यांकन करती है, तो इसे सरणी के अधिकतम सूचकांक की तुलना में एक से अधिक के रूप में व्याख्या की जाती है, इसलिए नकारात्मक सूचक सरणी के अंत से वापस आ जाते हैं, और एक -1 का सूचकांक अंतिम तत्व को संदर्भित करता है।

असाइनमेंट के लिए भी यही काम करता है। जब यह "अभिव्यक्ति" कहता है तो इसका अर्थ वास्तव में एक अभिव्यक्ति है; आप सूचकांक की गणना करने के लिए वहां किसी भी अंकगणितीय अभिव्यक्ति में लिख सकते हैं, जिसमें एक सरणी की लंबाई का ${#myarray[@]}स्पष्ट रूप से उपयोग करके गणना करना शामिल है ।


2
आप ऐसा kshऔर भी कर सकते हैं zsh
Janis

5
साथ zshहालांकि, द्वारा चूक सरणियों हैं 1 अनुक्रमित, के विपरीत bashऔर ksh0 से इंडैक्स कि वे कहाँ हैं।
स्टीफन किट

2
हां बिल्कुल; इस प्रश्न का संक्षिप्त उत्तर नहीं बदलता है, लेकिन चूंकि लंबे रूप का उल्लेख किया गया था इसलिए मुझे लगा कि वहां व्यवहार में अंतर को इंगित करना आवश्यक है।
स्टीफन किट

22
नेगेटिव इंडेक्स केवल 4.3 और इसके बाद के संस्करण में काम करते हैं।
cuonglm

10
मैक ओएस एक्स के साथ कम से कम v10.11.5 के रूप में शामिल बैश का संस्करण केवल 3.2 है, इसलिए यह मैक पर काम नहीं करता है।
Doktor J

44

आधुनिक बैश (v4.1 या बेहतर)

आप सूचकांक में अंतिम तत्व पढ़ सकते हैं -1:

$ a=(a b c d e f)
$ echo ${a[-1]}
f

नकारात्मक अनुक्रमित का उपयोग करके अंत से संख्यात्मक रूप से अनुक्रमित सरणियों तक पहुंचने के लिए समर्थन को संस्करण 4.1-अल्फा के साथ शुरू किया गया

पुराना बैश (v4.0 या पहले वाला)

आपको ${#a[@]}अंतिम तत्व प्राप्त करने के लिए सरणी लंबाई प्राप्त करनी होगी और फिर एक को घटाना होगा:

$ echo ${a[${#a[@]}-1]}
f

चूँकि बैश एरी सब्सक्राइब को एक अंकगणितीय अभिव्यक्ति के रूप में मानते हैं, अतः $((...))अंकगणितीय मूल्यांकन को बाध्य करने के लिए अतिरिक्त अंकन की आवश्यकता नहीं होती है ।


आखिरी मेरे लिए काम नहीं करता है; मैं बैश v4.1.2 (1) का उपयोग कर रहा हूं: अंतिम आइटम को प्रिंट करने के बजाय, यह पूरे सरणी को प्रिंट करता है।
अलेक्सज मगुरा

@ cuonglm का उत्तर हालांकि काम करता है।
अलेक्सज मैगुरा

यदि आप modernकिसी संस्करण के साथ अर्हता प्राप्त कर सकते हैं तो उत्तर और भी बेहतर होगा ।
सैमवेन

1
वास्तव में एवर को परफेक्ट बनाने के लिए क्या आवश्यक था।
सैमवेन

1
इसके लिए शुक्रिया। मैं गूंज $ {a [$ (($ {# a [@}} - 1])}} का उपयोग कर रहा था क्योंकि मुझे "बैश ट्रीट्स एरे सब्सक्रिप्शन के बारे में एक अंकगणितीय अभिव्यक्ति" के रूप में नहीं पता था।
ब्रूनो ब्रोंस्की

15

bashसरणी असाइनमेंट, संदर्भ, नकारात्मक सूचकांक के साथ परेशान केवल बैश 4.3 में जोड़े गए थे । पुराने संस्करण के साथ bash, आप इंडेक्स में अभिव्यक्ति का उपयोग कर सकते हैंarray[${#array[@]-1}]

एक और तरीका, पुराने संस्करण के साथ भी काम करें bash(बैश 3.0 या बेहतर):

$ a=([a] [b] [c] [d] [e])
$ printf %s\\n "${a[@]:(-1)}"
[e]

या:

$ printf %s\\n "${a[@]: -1}"
[e]

नकारात्मक ऑफसेट का उपयोग करके आप को अलग करने की जरूरत है :साथ -साथ भ्रमित किया जा रहा से बचने के लिए :-विस्तार।


1
बनाओ "${a[@]: -1}"और यह काम करेगा (इसके अलावा bashऔर zsh) में भी ksh
Janis

Kornshell डॉक्स ( www2.research.att.com/sw/download/man/man1/ksh.html ) इसे पूरी तरह से निर्दिष्ट करते हैं। (के डॉक्स का निरीक्षण किया है नहीं zshया bash, लेकिन मैं सभी तीन गोले में यह परीक्षण किया गया।)
जेनिस

@ जानिस: बैश डॉक्यूमेंटेशन को फिर से पढ़ें, इसमें इस बारे में भी बताया गया है। एक बार फिर धन्यवाद।
cuonglm

4

सरणी

सबसे पुराना विकल्प (bash 3.0+ के बाद से) bash में हैं:

$ a=(aa bb cc dd ee)
$ echo "${a[@]:(-1)}   ${a[@]: -1}   ${a[@]:(~0)}   ${a[@]:~0}"
ee   ee   ee   ee

विस्तार (डिफ़ॉल्ट मानों का उपयोग करें) के रूप में :माइनस के बाद की व्याख्या से बचने के लिए स्थान आवश्यक है ।-"${var:-abc}"

~अंकगणितीय है बिटवाइज़ निषेध (एक पूरक के बराबर या सभी बिट्स फ्लिप )। आदमी से मार:

आर्कटिक मूल्यांकन

      ! ~         logical and bitwise negation  

चूँकि bash-4.2 + भी:

$ echo "${a[-1]}   ${a[(~0)]}"
ee   ee

5.0+ के बाद से भी बैश करें:

$ echo "${a[~0]}"
ee

सभी बैश संस्करणों (पुराने बैश) के लिए:

$ echo "${a[   ${#a[@]}-1   ]}"    # spaces added **only** for readability
ee

@

स्थिति संबंधी तर्कों के लिए (२.०१ के बाद से):

$ set aa bb cc dd ee
$ echo "${@:(-1)} ${@:~0} ${@: -1} ${@:$#}   ${!#}"
ee ee ee   ee

सभी गोले का एक पोर्टेबल समाधान eval का उपयोग करना है:

eval printf '"%s\n"' \"\${$#}\"

क्या आपके पास बैश 5+ सिंटैक्स के लिए एक संदर्भ है? मैं के सभी 58 उदाहरणों की खोज ~में मार्गदर्शन और यह नहीं देखा।
टॉम हेल

... और आप इसे कैसे करते हैं $@? bash: ${@[@]:(-1)}: bad substitution
टॉम हेल

1
हां, एक man bashसंदर्भ है (@ शीर्षक पर विस्तारित उत्तर की जांच करें)। @ टोमहले
आइजैक

1
@है एक सरणी (ठीक है, नहीं पूरी तरह से एक सरणी ) बैश में है और यह सूचकांक (स्वीकार नहीं करता है []अलग-अलग तर्क के लिए) सबस्क्रिप्ट। आपको उपयोग ${@:(-1)}या समकक्ष करने की आवश्यकता है । @शीर्षक पर विस्तारित प्रविष्टि की जाँच करें । @ टोमहले
आइजैक

-2

इसके अलावा आप यह कर सकते हैं:

$ a=(a b c d e f)
$ echo ${a[$(expr ${#a[@]} - 1)]}

नतीजा:

$ f

आप जो कर रहे हैं वह सरणी में सभी तत्वों की गिनती प्राप्त कर रहा है और -1 घटाता है - क्योंकि आप सभी तत्वों को प्राप्त कर रहे हैं, जो कि सरणी इंडेक्स से शुरू नहीं है जो 0 है।

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