कैसे बैश में एक चर बढ़ाने के लिए?


608

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

Ubuntu 13.10 पर बैश संस्करण 4.2.45 (1) -release (x86_64-pc-linux-gnu)।

जवाबों:


946

बैश में एक चर को बढ़ाने के लिए एक से अधिक तरीके हैं, लेकिन आपने जो कोशिश की वह सही नहीं है।

आप उदाहरण अंकगणितीय विस्तार के लिए उपयोग कर सकते हैं :

var=$((var+1))
((var=var+1))
((var+=1))
((var++))

या आप उपयोग कर सकते हैं let:

let "var=var+1"
let "var+=1"
let "var++"

यह भी देखें: http://tldp.org/LDP/abs/html/dblparens.html


31
या ((++var))या ((var=var+1))या ((var+=1))
gniourf_gniourf

6
उत्सुकता से, var=0; ((var++))एक त्रुटि कोड देता है जबकि var=0; ((var++)); ((var++))ऐसा नहीं होता है। कोई विचार क्यों?
फुनेहे

15
@phunehehe देखो help '(('। अंतिम पंक्ति कहती है:Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise.
राडु रियडेनु

2
मुझे संदेह 1है कि शून्य के मूल्यांकन में क्यों @ gniourf_gniourf की टिप शामिल है ((++var))लेकिन नहीं ((var++))
DreadPirateShawn

4
यह let var++उद्धरण के बिना उपयोग करने के लिए सुरक्षित है ?
वजंड्रिया

160
var=$((var + 1))

बैश में अंकगणित $((...))वाक्यविन्यास का उपयोग करता है।


9
स्वीकार किए गए उत्तर से बेहतर है। केवल 10% अधिक स्थान में, आप पर्याप्त उदाहरण प्रदान करने में कामयाब रहे (एक बहुत - नौ उस बिंदु पर ओवरकिल है जब आप बस दिखावा कर रहे हैं), और आपने हमें यह जानने के लिए पर्याप्त जानकारी प्रदान की कि ((...))अंकगणित का उपयोग करने की कुंजी क्या है बाश में। मुझे महसूस नहीं हुआ कि बस स्वीकृत उत्तर को देख रहा था - मैंने सोचा कि परिचालन के आदेश के बारे में नियमों का एक अजीब सेट है या स्वीकृत उत्तर में सभी कोष्ठक के लिए अग्रणी है।
आर्टऑफवर्फ

82

विभिन्न विकल्पों का प्रदर्शन विश्लेषण

राडू रियडेनु के उत्तर के लिए धन्यवाद जो बैश में एक चर को बढ़ाने के लिए निम्नलिखित तरीके प्रदान करता है:

var=$((var+1))
((var=var+1))
((var+=1))
((var++))
let "var=var+1"
let "var+=1" 
let "var++"

और भी तरीके हैं। उदाहरण के लिए, इस प्रश्न पर अन्य उत्तरों में देखें।

let var++
var=$((var++))
((++var))
{
    declare -i var
    var=var+1
    var+=1
}
{
    i=0
    i=$(expr $i + 1)
}

इतने सारे विकल्प होने से इन दो सवालों का सामना करना पड़ता है:

  1. क्या उनके बीच एक प्रदर्शन अंतर है?
  2. यदि ऐसा है, जो सबसे अच्छा प्रदर्शन करता है?

वृद्धिशील प्रदर्शन परीक्षण कोड:

#!/bin/bash

# To focus exclusively on the performance of each type of increment
# statement, we should exclude bash performing while loops from the
# performance measure. So, let's time individual scripts that
# increment $i in their own unique way.

# Declare i as an integer for tests 12 and 13.
echo > t12 'declare -i i; i=i+1'
echo > t13 'declare -i i; i+=1'
# Set i for test 14.
echo > t14 'i=0; i=$(expr $i + 1)'

x=100000
while ((x--)); do
    echo >> t0 'i=$((i+1))'
    echo >> t1 'i=$((i++))'
    echo >> t2 '((i=i+1))'
    echo >> t3 '((i+=1))'
    echo >> t4 '((i++))'
    echo >> t5 '((++i))'
    echo >> t6 'let "i=i+1"'
    echo >> t7 'let "i+=1"'
    echo >> t8 'let "i++"'
    echo >> t9 'let i=i+1'
    echo >> t10 'let i+=1'
    echo >> t11 'let i++'
    echo >> t12 'i=i+1'
    echo >> t13 'i+=1'
    echo >> t14 'i=$(expr $i + 1)'
done

for script in t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14; do
    line1="$(head -1 "$script")"
    printf "%-24s" "$line1"
    { time bash "$script"; } |& grep user
    # Since stderr is being piped to grep above, this will confirm
    # there are no errors from running the command:
    eval "$line1"
    rm "$script"
done

परिणाम:

i=$((i+1))              user    0m0.992s
i=$((i++))              user    0m0.964s
((i=i+1))               user    0m0.760s
((i+=1))                user    0m0.700s
((i++))                 user    0m0.644s
((++i))                 user    0m0.556s
let "i=i+1"             user    0m1.116s
let "i+=1"              user    0m1.100s
let "i++"               user    0m1.008s
let i=i+1               user    0m0.952s
let i+=1                user    0m1.040s
let i++                 user    0m0.820s
declare -i i; i=i+1     user    0m0.528s
declare -i i; i+=1      user    0m0.492s
i=0; i=$(expr $i + 1)   user    0m5.464s

निष्कर्ष:

ऐसा लगता है कि i+=1जब $iपूर्णांक के रूप में घोषित किया जाता है , तो प्रदर्शन तेज होता है। letबयान विशेष रूप से धीमी गति से लगते हैं, और exprअब तक सबसे धीमे हैं क्योंकि यह बिलियन नहीं है।


जाहिरा तौर पर गति कमांड लंबाई के साथ संबंधित है। मुझे आश्चर्य है कि क्या कमांड एक ही फ़ंक्शन को कॉल करते हैं।
मैथोकॉक

18

यह भी है:

var=`expr $var + 1`

रिक्त स्थान की सावधान नोट ले लो और भी ` नहीं है '

जबकि रादु के जवाब, और टिप्पणियां, संपूर्ण और बहुत सहायक हैं, वे बैश-विशिष्ट हैं। मुझे पता है कि आपने विशेष रूप से बैश के बारे में पूछा था, लेकिन मुझे लगा कि जब मैं uCLinux के तहत बिजीबॉक्स में श का उपयोग कर एक ही काम करना चाह रहा था, तब से मुझे यह प्रश्न मिला, क्योंकि मुझे यह प्रश्न मिला। बैश से परे यह पोर्टेबल।


1
आप इसका उपयोग भी कर सकते हैंi=$((i+1))
wjandrea

यदि प्रक्रिया प्रतिस्थापन $(...)इस शेल पर उपलब्ध है, तो मैं इसके बजाय इसका उपयोग करने की सलाह दूंगा।
रेडॉन रोसबोरो


7

सभी उत्तरों में एक विधि गायब है - bc

$ VAR=7    
$ bc <<< "$VAR+2"
9
$ echo $VAR
7
$ VAR=$( bc <<< "$VAR+1" )
$ echo $VAR
8

bcPOSIX मानक द्वारा निर्दिष्ट है , इसलिए उबंटू और POSIX-compliant सिस्टम के सभी संस्करणों पर मौजूद होना चाहिए। <<<पुनर्निर्देशन करने के लिए परिवर्तित किया जा सकता है echo "$VAR" | bcपोर्टेबिलिटी के लिए, लेकिन जब से सवाल के बारे में पूछता है bash- यह सिर्फ उपयोग करना ठीक है <<<


6

वापसी कोड 1मुद्दा सभी डिफ़ॉल्ट वेरिएंट (के लिए मौजूद है let, (()), आदि)। यह अक्सर परेशानियों का कारण बनता है, उदाहरण के लिए, उपयोग की जाने वाली लिपियों में set -o errexit। यहाँ मैं 1गणित के भावों से त्रुटि कोड को रोकने के लिए उपयोग कर रहा हूं जो मूल्यांकन करते हैं 0;

math() { (( "$@" )) || true; }

math a = 10, b = 10
math a++, b+=2
math c = a + b
math mod = c % 20
echo $a $b $c $mod
#11 12 23 3

0

इस तरह के एक सरल कार्य को पूरा करने के लिए यह सबसे खराब तरीका है, लेकिन मैं इसे मज़े के लिए दस्तावेज़ करना चाहता था जो मुझे लगता है (कोड गोल्फ के पूर्ण विपरीत)।

$ var=0
$ echo $var
0
$ var="$(python -c 'print('$var'+1)')"
$ echo $var
1

या

$ var="$(printf '%s\n' $var'+1' | bc)"
$ echo $var
1

गंभीरता से यहां एक और बेहतर विकल्प का उपयोग करें।

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