POSIX खोल स्क्रिप्ट में छद्म सरणियों का उपयोग कैसे करें?


6

POSIX खोल स्क्रिप्ट में छद्म सरणियों का उपयोग कैसे करें?

मैं Bash स्क्रिप्ट में 10 पूर्णांक की एक सरणी को POSIX शेल स्क्रिप्ट में कुछ समान के साथ बदलना चाहता हूं ।

मैं रिच के श (POSIX शेल) ट्रिक्स में आने में कामयाब रहा , सेक्शंस के साथ काम करना

मैंने क्या कोशिश की:

save_pseudo_array()
{
    for i do
        printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
    done
    echo " "
}

coords=$(save_pseudo_array "$@")
set -- 1895 955 1104 691 1131 660 1145 570 1199 381
eval "set -- $coords"

मैं इसे समझ नहीं पाया, यही समस्या है, अगर किसी ने इस पर कुछ प्रकाश डाला, बहुत सराहना की।

जवाबों:


8

विचार मनमाने ढंग से तार की सूची को एक अदिश चर में एक प्रारूप में संलग्न करने के लिए है जिसका उपयोग बाद में सूची या मनमाने तार के पुनर्निर्माण के लिए किया जा सकता है।

 $ save_pseudo_array x "y z" $'x\ny' "a'b"
'x' \
'y z' \
'x
y' \
'a'\''b' \

$

जब आप उसके set --सामने चिपके रहते हैं , तो यह शेल कोड बनाता है जो उस सूची को फिर से संगठित करता है x, y zतार करता है और इसे $@सरणी में संग्रहीत करता है , जिसे आपको बस evalयूटेट करने की आवश्यकता है ।

sed(कहते हैं ठीक से प्रत्येक स्ट्रिंग के हवाले का ख्याल रखता है ', पहली पंक्ति की शुरुआत में अंतिम पंक्ति के अंत में और बदल देता है सभी 'के साथ है '\'')।

हालांकि, इसका मतलब है कि प्रत्येक तर्क के लिए एक printfऔर sedकमांड चल रहा है, इसलिए यह काफी अक्षम है। यह सिर्फ एक अजीब आह्वान के साथ अधिक सरल तरीके से किया जा सकता है:

save_pseudo_array() {
  LC_ALL=C awk -v q=\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q "\\" q q, ARGV[i])
        printf "%s ", q ARGV[i] q
      }
      print ""
    }' "$@"
}

वहाँ कुछ पोर्टेबिलिटी दक्षता के बारे में यहाँ बनाम के बारे में कहा जा रहा है printf ... | sed ...बनाम awk, हालांकि: मैं के सभी व्यावहारिक बारीकियों याद नहीं है awkपोर्टेबिलिटी बनाम sed, लेकिन यह निश्चित रूप से एक बड़ा सुरंग है। यदि लक्ष्य बस कड़ाई से POSIX है, तो यह ठीक हो सकता है, लेकिन यदि लक्ष्य आज व्यावहारिक उपयोग में सिस्टम के लिए व्यावहारिक पोर्टेबिलिटी है, तो यह नहीं हो सकता है।
mtraceur

@mtraceur, AWK POSIX का हिस्सा है और काफी पोर्टेबल है (यदि आप GNU एक्सटेंशन से बचते हैं)। (और मुझे एहसास है कि आप यह नहीं कह रहे हैं कि यह POSIX का हिस्सा नहीं है।)
स्टीफन किट

1
@mtraceur, हाँ मूल रूप से, यहाँ समस्या /bin/awkसोलारिस की होगी जो 70 के दशक के अंत में यूनिक्स V7 से एपीआई के साथ एक है (इसलिए बिना -v, ARGV...)। सोलारिस पर कहा कि, इसमें एक POSIX awkहै /usr/xpg4/bin/awk, और आमतौर पर सोलारिस पर आप जानते हैं कि आप डिफ़ॉल्ट वातावरण से बहुत उम्मीद नहीं कर सकते हैं और आपको PATH=$(getconf PATH):$PATHकुछ भी करने में सक्षम होने की आवश्यकता है।
स्टीफन चेजेलस

@ StéphaneChazelas आप LC_ALL=Cअपने awkआदेश के साथ उपयोग कर रहे हैं एक विशेष कारण है ? जब तक आप ==ऑपरेटर के साथ तार की तुलना नहीं कर रहे थे, मुझे ऐसा करने की ज़रूरत नहीं थी ।
हेरोल्ड फिशर

9

मूल विचार setएक सरणी से अनुक्रमित मूल्यों के साथ काम करने के अनुभव को फिर से बनाने के लिए उपयोग करना है। इसलिए जब आप किसी सरणी के साथ काम करना चाहते हैं, तो आप setमूल्यों के साथ चलते हैं; कि

set -- 1895 955 1104 691 1131 660 1145 570 1199 381

तो फिर तुम उपयोग कर सकते हैं $1, $2, forआदि दिए गए मूल्यों के साथ काम करने के लिए।

यदि आपको एक से अधिक सरणियों की आवश्यकता है, तो इसका अधिक उपयोग नहीं किया जा सकता है। यही कारण है कि जहां है saveऔर eval: चाल में आता है रिच के saveसमारोह ¹ वर्तमान स्थितीय मापदंडों संसाधित करता है और एक स्ट्रिंग आउटपुट उचित के हवाले से, है, जो तब के साथ इस्तेमाल किया जा सकता evalसंग्रहीत मूल्यों को बहाल करने की। इस प्रकार आप चलाते हैं

coords=$(save "$@")

वर्तमान कार्य सरणी को सहेजने के लिए coords, फिर एक नया सरणी बनाएं, उसके साथ काम करें, और जब आपको coordsफिर से काम करने की आवश्यकता हो , तो आप evalइसे करें:

eval "set -- $coords"

आपको जिस उदाहरण पर विचार करना है, उसे समझने के लिए आप यहाँ दो सरणियों के साथ काम कर रहे हैं, एक जो पहले से निर्धारित मानों के साथ है, और जिसे आप स्टोर करते हैं coords, और 1895, 955 इत्यादि वाले सरणी। स्निपेट स्वयं ही वह सब नहीं बनाता है। अपने आप समझ में, आप setऔर evalलाइनों के बीच कुछ प्रसंस्करण होगा । यदि आपको 1895, 955 के बाद में लौटने की आवश्यकता है, तो आप इसे पुनर्स्थापित करने से पहले सहेजेंगे coords:

newarray=$(save "$@")
eval "set -- $coords"

इस तरह आप $newarrayबाद में पुनर्स्थापित कर सकते हैं ।


As के रूप में परिभाषित किया गया

save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}


यह saveफ़ंक्शन कहाँ परिभाषित किया गया है?
ʇsәɹoɈ

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