एक्सप्रेश अंकगणित में कोष्ठक: 3 * (2 + 1)


59

expr कोष्ठक की तरह नहीं लगता है (स्पष्ट ऑपरेटर प्राथमिकता के लिए गणित में प्रयुक्त):

expr 3 * (2 + 1)
bash: syntax error near unexpected token `('

बाश में ऑपरेटर प्राथमिकता को कैसे व्यक्त करें?

जवाबों:


40

letबैश बिलिन का उपयोग करने का दूसरा तरीका :

$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9

ध्यान दें

जैसा कि @ स्टीफन चेज़ेलस ने कहा , bashआपको विरासत में या उससे ((...))अधिक अंकगणित करने के लिए उपयोग करना चाहिए ।exprlet

पोर्टेबिलिटी के लिए $((...)), @ बर्नहार्ड जवाब की तरह उपयोग करें ।


1
+1 और भी पठनीय! मैंने अपना प्रश्न + उत्तर पोस्ट किया यह सोचकर कि यह मेरे साथी लिनक्स उपयोगकर्ताओं के लिए उपयोगी होगा, लेकिन अब मुझे दूसरे उत्तरों से बहुत लाभ मिल रहा है :-)
निकोलस राउल

3
उपयोग करने का कोई कारण नहीं है let। यह किसी भी अधिक मानक या पोर्टेबल की तुलना में नहीं है (( a = 3 * (2 + 1) ))(दोनों से आते हैं kshऔर केवल ksh, bash और zsh में उपलब्ध हैं) और यह कम सुपाठ्य या उद्धरण के लिए आसान है। a=$((3 * (2 + 1)))पोर्टेबल होने के लिए उपयोग करें ।
स्टीफन चेज़लस

2
मैं यह नहीं कह रहा कि यह गलत है, मैं यह कह रहा हूं कि इसका उपयोग नहीं किया जाना चाहिए क्योंकि बेहतर विकल्प हैं (सुगमता के ((a = 3 * (2 + 1) ))लिए एक है, पोर्टेबिलिटी के लिए एक a=$((3 * (2 + 1)))), इसलिए यह आपके या आपके उत्तर के खिलाफ नोट नहीं है लेकिन इसके लिए चयनित उत्तर होने के खिलाफ है और शीर्ष स्कोरर।
स्टीफन चेज़लस

@ स्टीफनचेज़ेलस: मेरा जवाब अपडेट करें!
cuonglm

मैंने हमेशा इस्तेमाल किया है a=1 $[a+2]या a=1 b=2 $[a+b]। क्या उनका कारण उस वाक्य रचना से बचना है?
गॉर्डन

73

आप इसके बजाय अंकगणितीय विस्तार का उपयोग कर सकते हैं।

echo "$(( 3 * ( 2 + 1 ) ))"
9

मेरी व्यक्तिगत राय में, यह प्रयोग करने की तुलना में थोड़ा अच्छा है expr

से man bash

अंकगणित विस्तार अंकगणित विस्तार एक अंकगणितीय अभिव्यक्ति के मूल्यांकन और परिणाम के प्रतिस्थापन की अनुमति देता है। अंकगणितीय विस्तार के लिए प्रारूप है:

         $((expression))

अभिव्यक्ति को ऐसे माना जाता है जैसे कि यह दोहरे उद्धरण चिह्नों के भीतर है, लेकिन कोष्ठकों के अंदर एक दोहरे उद्धरण का विशेष रूप से व्यवहार नहीं किया जाता है। अभिव्यक्ति में सभी टोकन पैरामीटर विस्तार, स्ट्रिंग विस्तार, कमांड प्रतिस्थापन और उद्धरण हटाने से गुजरते हैं। अंकगणित विस्तार को नेस्टेड किया जा सकता है।

मूल्यांकन ARITHMETIC EVALUATION के तहत नीचे सूचीबद्ध नियमों के अनुसार किया जाता है। यदि अभिव्यक्ति अमान्य है, तो बैश एक संदेश को दर्शाता है जो विफलता का संकेत देता है और कोई प्रतिस्थापन नहीं होता है।


1
पठनीयता के अलावा, इसे अंकगणित करने के लिए एक अतिरिक्त प्रक्रिया की आवश्यकता नहीं है; यह स्वयं शेल द्वारा नियंत्रित किया जाता है।
chepner

ध्यान दें कि POSIX गोले में, यह शब्द विभाजन के अधीन है, इसलिए इसे सूची संदर्भों में उद्धृत करना एक अच्छी आदत है।
स्टीफन चेजलस 15

जब मैं बैश शेल में यह कोशिश करता हूं तो मुझे 'अवैध चर नाम' मिलता है। "
लॉर्डहॉग

40

exprआधुनिक गोले में अंकगणित का उपयोग करने का कोई कारण नहीं है ।

POSIX $((...))विस्तार ऑपरेटर को परिभाषित करता है । तो आप सभी POSIX आज्ञाकारी गोले में ( shसभी आधुनिक यूनिक्स-पसंद, डैश, बैश, यश, mshh, zsh, पॉश, ksh ...) का उपयोग कर सकते हैं।

a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))

kshएक letबिल्टिन भी पेश किया, जो एक ही तरह की अंकगणितीय अभिव्यक्ति के रूप में दिया गया है, कुछ में विस्तार नहीं करता है, लेकिन अभिव्यक्ति के 0 या नहीं के आधार पर बाहर निकलने की स्थिति देता है, जैसे expr:

if let 'a = 3 * (2 + 1)'; then
  echo "$a is non-zero"
fi

हालाँकि, जैसा कि उद्धरण इसे अजीब बनाता है और बहुत सुपाठ्य नहीं है ( exprनिश्चित रूप से उसी हद तक नहीं ), kshएक ((...))वैकल्पिक विकल्प भी प्रस्तुत किया है :

if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
  echo "$a is non-zero and 3 > 1"
fi
((a+=2))

जो बहुत अधिक सुपाठ्य है और इसके स्थान पर इसका उपयोग किया जाना चाहिए।

letऔर ((...))में ही उपलब्ध हैं ksh, zshऔर bash$((...))वाक्य रचना प्राथमिकता दी जानी चाहिए अगर अन्य गोले को पोर्टेबिलिटी की जरूरत है, exprकेवल पूर्व POSIX बॉर्न की तरह गोले (आमतौर पर बॉर्न शैल या Almquist खोल के प्रारंभिक संस्करणों) के लिए आवश्यक है।

गैर-बॉर्न मोर्चे पर, अंतर्निहित अंकगणित ऑपरेटर के साथ कुछ गोले हैं:

  • csh/ tcsh(वास्तव में अंकगणित मूल्यांकन के साथ पहला यूनिक्स खोल)

    @ a = 3 * (2 + 1)
  • akanga(पर आधारित rc)

    a = $:'3 * (2 + 1)'
  • एक इतिहास के रूप में, अल्मक्विस्ट शेल के मूल संस्करण, जैसा कि 1989 में यूनेट पर पोस्ट किया गया था, में एक exprबिल्डिन (वास्तव में विलय हुआ test) था, लेकिन इसे बाद में हटा दिया गया था।


मैं आपसे, स्टीफन से हर दिन कुछ नया सीखता हूं। मैं आपके POSIX खोल ज्ञान की बहुत सराहना करता हूं!
मैटबिएंको

कैसे के बारे में : $((a = a*2))?
आर्थर २ ई ५

यदि मेरे पास एक अस्थायी बिंदु है तो क्या होगा? मेरी अभिव्यक्ति एक = $ ((-14 + 0.2 * (1 + 2 + 3)) है)। त्रुटि टोकन ".2 * (1 + 2 + 3)" है
Blaise

@Blaise, तो आपको एक शेल की आवश्यकता होगी $((...))जो zsh, ksh93 या यश जैसे फ्लोटिंग पॉइंट का समर्थन करता है ।
स्टीफन चेजलस

16

exprएक बाहरी कमांड है, यह विशेष शेल सिंटैक्स नहीं है। इसलिए, यदि आप exprशेल विशेष वर्णों को देखना चाहते हैं, तो आपको उन्हें उद्धृत करके शेल पार्सिंग से बचाने की आवश्यकता है। इसके अलावा, exprप्रत्येक संख्या और ऑपरेटर को एक अलग पैरामीटर के रूप में पारित करने की आवश्यकता होती है। इस प्रकार:

expr 3 \* \( 2 + 1 \)

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

echo "$((3 * (2 + 1)))"

निर्माण $((…))अंकगणित अभिव्यक्ति (दशमलव में लिखा गया) के परिणाम तक फैलता है। बैश, अधिकांश गोले की तरह, केवल पूर्णांक अंकगणितीय मोडुलो 2 64 (या 32 बिट मशीनों पर बैश के पुराने संस्करणों और कुछ अन्य गोले के लिए मॉडुलो 2 32 ) का समर्थन करता है।

बैश एक अतिरिक्त सुविधा सिंटैक्स प्रदान करता है जब आप असाइनमेंट निष्पादित करना चाहते हैं या परीक्षण करना चाहते हैं कि कोई अभिव्यक्ति 0 है, लेकिन परिणाम के बारे में परवाह नहीं है। यह निर्माण ksh और zsh में भी मौजूद है लेकिन सादे श में नहीं।

((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then 

पूर्णांक अंकगणितीय के अलावा, exprकुछ स्ट्रिंग हेरफेर फ़ंक्शन प्रदान करता है। ये भी POSIX गोले की विशेषताओं के आधार पर तय किए गए हैं, एक को छोड़कर: यह expr STRING : REGEXPपरीक्षण करता है कि क्या स्ट्रिंग निर्दिष्ट regexp से मेल खाती है। एक POSIX शेल बाहरी उपकरणों के बिना ऐसा नहीं कर सकता है, लेकिन bash [[ STRING =~ REGEXP ]](एक अलग regexp सिंटैक्स के साथexprएक क्लासिक टूल है और BRE का उपयोग करता है, bash ERE का उपयोग करता है)।

जब तक आप 20-वर्षीय सिस्टम पर चलने वाली स्क्रिप्ट्स को मेनटेन नहीं कर रहे हैं, आपको यह जानने की आवश्यकता नहीं है कि exprकभी अस्तित्व में था। शेल अंकगणित का उपयोग करें।


expr foo : '\(.\)'पाठ निष्कर्षण भी करता है। bashकी BASH_REMATCHऐसी ही कुछ प्राप्त होता है। यह स्ट्रिंग तुलना भी करता है, जो कि POSIX [नहीं करता है (हालांकि कोई इसके लिए उपयोग करने के तरीकों की कल्पना कर सकता sortहै)।
स्टीफन चेज़लस

सिंटेक्स प्लेसहोल्डर के रूप में अंडरस्कोर --- आप एक स्कीमर, @ गिल्स? :]
रूबीट्यूडे डोनो

1
@RubyTuesdayDONO मैंने यहां अंडरस्कोर का उपयोग नहीं किया। क्या आप U + 2026 HORIZONTAL ELLIPSIS का गलत इस्तेमाल कर रहे हैं? यदि हां, तो एक बड़े फ़ॉन्ट का उपयोग करके देखें।
गिल्स

@ गिल्स - ठीक है, हाँ, यह केवल मेरे फ़ॉन्ट आकार के कारण अंडरस्कोर जैसा दिखता है। मेरे लिए, "शेमर" एक पूरक है, और यह किसी भी तरह से दीर्घवृत्त जैसा नहीं है। अंडरस्कोर का अर्थ वैसे भी बदल जाता है ... इस पर
झपकी

12

उद्धरण के साथ कोष्ठक का प्रयोग करें:

expr 3 '*' '(' 2 '+' 1 ')'
9

उद्धरण को कोष्ठक के रूप में कोष्ठक की व्याख्या करने से बैश को रोकते हैं।


2
निकोलस क्या दिखाता है, लेकिन यह नहीं समझाता है कि exprकमांड लाइन पर टोकन को रिक्त स्थान द्वारा अलग किया जाना चाहिए; इसलिए; उदाहरण के लिए, expr 3 "*" "(2" "+" "1)" काम नहीं करेगा । (इसके अलावा, BTW, आपको शायद उद्धृत करने की आवश्यकता नहीं है +।)
G-Man

कोष्ठक जैसे खोजशब्द नहीं हैं whileऔर [[, वे वाक्यविन्यास हैं। यदि वे कीवर्ड थे, तो उन्हें इस तरह के कमांड तर्क में व्याख्यायित नहीं किया जाएगा। आपको उद्धरण चिह्नों की आवश्यकता होती है ताकि बैश उन्हें पार्स न करे, बल्कि एक स्ट्रिंग शाब्दिक देखता है
गाइल्स

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