मैं बीच के कुछ सूचकांक में एक बैश सरणी को कैसे स्थानांतरित कर सकता हूं?


12
1  #!/bin/bash
2  # query2.sh
3
4  numbers=(53 8 12 9 784 69 8 7 1)
5  i=4
6
7  echo ${numbers[@]} # <--- this echoes "53 8 12 9 784 69 8 7 1" to stdout.
8  echo ${numbers[i]} # <--- this echoes "784" to stdout.
9
10 unset numbers[i]
11
12 echo ${numbers[@]} # <--- this echoes "53 8 12 9 69 8 7 1" to stdout.
13 echo ${numbers[i]} # <--- stdout is blank.

क्यों, लाइन 13 में, स्टडआउट खाली है, यह देखते हुए कि सरणी को लाइन 12 के स्टडआउट द्वारा अपडेट किया गया लगता है?

और इसलिए, मुझे इच्छित उत्तर पाने के लिए क्या करना चाहिए, "69"?


1
कोडिंग के प्रकार को ध्यान में रखते हुए इस प्रश्न का तात्पर्य है, आपको चेतावनी देनी चाहिए: देखें कि क्या मेरी स्क्रिप्ट में कुछ गड़बड़ है या क्या बैथ पायथन की तुलना में बहुत धीमा है?
वाइल्डकार्ड

जवाबों:


21

unsetएक तत्व निकालता है। यह शेष तत्वों को फिर से नहीं बनाता है।

हम declare -pवास्तव में देखने के लिए उपयोग कर सकते हैं numbers:

$ unset "numbers[i]"
$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [5]="69" [6]="8" [7]="7" [8]="1")

numbersअब एक तत्व है निरीक्षण करें 4

एक और उदाहरण

का निरीक्षण करें:

$ a=()
$ a[1]="element 1"
$ a[22]="element 22"
$ declare -p a
declare -a a=([1]="element 1" [22]="element 22")

ऐरे के aपास 21 के माध्यम से कोई तत्व 2 नहीं है। बैश को सरणी सूचकांकों के लगातार होने की आवश्यकता नहीं है।

सूचकांकों के एक नयाकरण के लिए मजबूर करने के लिए सुझाई गई विधि

आइए numbersअनुपलब्ध तत्व के साथ सरणी से शुरू करें 4:

$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [5]="69" [6]="8" [7]="7" [8]="1")

यदि हम चाहते हैं कि सूचकांकों को बदलना है, तो:

$ numbers=("${numbers[@]}")
$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [4]="69" [5]="8" [6]="7" [7]="1")

अब एक तत्व संख्या है 4और इसका मूल्य है 69

एक कदम में एक तत्व और रेनमर सरणी को हटाने के लिए वैकल्पिक विधि

फिर से, चलो परिभाषित करते हैं numbers:

$ numbers=(53 8 12 9 784 69 8 7 1)

जैसा कि टिप्पणियों में टोबी स्पाइट द्वारा सुझाया गया है , चौथे तत्व को हटाने की एक विधि और शेष तत्वों को एक चरण में सभी को फिर से लिखना है:

$ numbers=("${numbers[@]:0:4}" "${numbers[@]:5}")
$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [4]="69" [5]="8" [6]="7" [7]="1")

जैसा कि आप देख सकते हैं, चौथा तत्व हटा दिया गया था और सभी शेष तत्व फिर से बनाए गए थे।

${numbers[@]:0:4}स्लाइस सरणी numbers: यह तत्व 0 से शुरू होने वाले पहले चार तत्वों को लेता है।

इसी प्रकार, ${numbers[@]:5}स्लाइस ऐरे numbers: इसमें एलिमेंट 5 से शुरू होने वाले और एरे के अंत तक जारी रखने वाले सभी तत्व लगते हैं।

किसी सरणी के सूचकांकों को प्राप्त करना

मान एक सरणी के साथ प्राप्त किया जा सकता ${a[@]}। उन मूल्यों के अनुरूप होने वाले सूचकांकों (या कुंजियों ) को खोजने के लिए उपयोग करें ${!a[@]}

उदाहरण के लिए, numbersलापता तत्व के साथ फिर से हमारे सरणी पर विचार करें 4:

$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [5]="69" [6]="8" [7]="7" [8]="1")

यह देखने के लिए कि कौन से सूचकांक असाइन किए गए हैं:

$ echo "${!numbers[@]}"
0 1 2 3 5 6 7 8

फिर, 4सूचकांक की सूची से गायब है।

प्रलेखन

से man bash:

unsetBuiltin सरणियों नष्ट करने के लिए प्रयोग किया जाता है। unset name[subscript]सूचकांक में सरणी तत्व को नष्ट कर देता है subscript। अनुक्रमित सरणियों के लिए नकारात्मक सदस्यता ऊपर वर्णित के रूप में व्याख्या की जाती है। पाथनेम विस्तार के कारण होने वाले अवांछित दुष्प्रभावों से बचने के लिए देखभाल की जानी चाहिए। unset name, जहां nameएक सरणी है, या unset name[subscript], जहां subscriptहै * या @, पूरे सरणी को निकालता है।


1
ध्यान दें कि शेल ऐरे सिंटैक्स वास्तव में सिर्फ इसी तरह से नामांकित चर से निपटने के लिए आसान बनाने का एक तरीका है। कोई सरणी ही नहीं है; वास्तव में, आपके लिखने के बाद a=(), चर aअभी भी अपरिभाषित है जब तक आप वास्तव में इसके किसी एक सूचक को असाइन नहीं करते हैं।
शेपनर

@ John1024: इस उत्तर के लिए धन्यवाद। क्या आप संभावित परिणाम प्राप्त करने के लिए सुझाए गए उत्तर को शामिल करने के लिए संभवतः इसका विस्तार कर सकते हैं?
एंथनी वेबर

@AnthonyWebber ज़रूर। मैंने जवाब के एक खंड को यह दिखाने के लिए जोड़ा कि कैसे सूचकांकों के एक नए सिरे से मजबूर करने के लिए।
जॉन १०२४२

2
बस एक वैकल्पिक दृष्टिकोण का उल्लेख करने के लिए (जो कुछ कोड के लिए बेहतर फिट हो सकता है): इसके बजाय unset numbers[4], स्लाइसिंग का उपयोग करके पूरे सरणी को असाइन करें, अर्थात numbers=("${numbers[@]:0:4}" "${numbers[@]:5}")(मैं उत्तर के रूप में पोस्ट करूंगा, लेकिन ठीक से समझाने के लिए समय नहीं है)।
टोबे स्पाइट

@ John1024: आप ऐसा कर रहे हैं। और थंक्स टोबी :)
एंथनी वेबर

5

bashजैसे kshसरणियाँ, वास्तव में सरणियाँ नहीं हैं, वे सकारात्मक पूर्णांक (या तथाकथित विरल सरणियों ) तक सीमित कुंजी के साथ सहयोगी सरणियों की तरह हैं । असली सरणियों के साथ एक खोल के लिए, आप की तरह के गोले पर एक नज़र हो सकता है rc, es, fish, yash, zsh(या csh/ tcshवे बेहतर से परहेज कर रहे हैं, हालांकि उन गोले इतने सारे मुद्दे हैं)।

में zsh:

a=(1 2 3 4 5)
a[3]=() # remove the 3rd element
a[1,3]=() # remove the first 3 elements
a[-1]=() # remove the last element

(ध्यान दें कि zsh में, unset 'a[3]'वास्तव में बेहतर संगतता के लिए इसे खाली स्ट्रिंग पर सेट करता है ksh)

में yash:

a=(1 2 3 4 5)
array -d a 3 # remove the 3rd element
array -d a 1 2 3 # remove the first 3 elements
array -d a -1 # remove the last element

में fish(नहीं एक बॉर्न की तरह करने के लिए खोल विपरीत bash/ zsh):

set a 1 2 3 4 5
set -e a[3] # remove the 3rd element
set -e a[1..3] # remove the first 3 elements
set -e a[-1] # remove the last element

में es(आधार पर rc, बॉर्न की तरह नहीं)

a = 1 2 3 4 5
a = $a(... 2 4 ...) # remove the 3rd element
a = $a(4 ...) # remove the first 3 elements
a = $a(... `{expr $#a - 1}) # remove the last element
# or a convoluted way that avoids forking expr:
a = $a(... <={@{*=$*(2 ...); return $#*} $a})

में kshऔरbash

यदि आप करते हैं तो आप सरणियों को सामान्य सरणियों के रूप में उपयोग कर सकते हैं:

a=("${a[@]}")

प्रत्येक डिलीट या इंसर्ट ऑपरेशंस के बाद, जिन्होंने अनुक्रमणिका की सूची को सन्निहित नहीं बनाया है या 0. पर शुरू नहीं किया है। यह भी ध्यान दें कि ksh/ bashसरणियाँ 0 से शुरू होती हैं, 1 नहीं $@(कुछ मायनों को छोड़कर )।

यह वास्तव में तत्वों को सुव्यवस्थित करेगा और उन्हें अनुक्रम 0, 1, 2 ... अनुक्रम में ले जाएगा।

यह भी ध्यान दें कि आपको इसमें उद्धृत करने की आवश्यकता है number[i]:

unset 'number[i]'

अन्यथा, यह माना जाएगा कि वर्तमान निर्देशिका में unset numberiएक फ़ाइल है numberi

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