විචල්ය බෑෂ් වලින් වැඩි කරන්නේ කෙසේද?


657

දෙකම භාවිතා කරමින් var=$var+1සහ var=($var+1)සාර්ථක නොවී සංඛ්‍යාත්මක විචල්‍යයක් වැඩි කිරීමට මම උත්සාහ කර ඇත්තෙමි . විචල්‍යය අංකයකි, නමුත් බාෂ් එය නූලක් ලෙස කියවන බවක් පෙනේ.

උබුන්ටු 13.10 හි 4.2.45 (1) -ප්‍රකාශනය (x86_64-pc-linux-gnu).

Answers:


1024

විචල්යයන් වැඩි කිරීමට එක් ක්‍රමයකට වඩා තිබේ, නමුත් ඔබ උත්සාහ කළ දේ නිවැරදි නොවේ.

උදාහරණයක් ලෙස අංක ගණිත ප්‍රසාරණය ඔබට භාවිතා කළ හැකිය :

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 .


35
හෝ ((++var))හෝ ((var=var+1))හෝ ((var+=1)).
gniourf_gniourf

8
කුතුහලය දනවන කරුණ නම්, නැති var=0; ((var++))විට දෝෂ කේතයක් ලබා var=0; ((var++)); ((var++))දීමයි. කිසියම් අදහසක් ඇයි?
phunehehe

16
බලන්න help '(('. අන්තිම පේළියේ මෙසේ සඳහන් වේ:Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise.
රාදු රදීනු

2
1Z gniourf_gniourf හි ඉඟියට ඇතුළත් ((++var))නමුත් එයට ඇතුළත් නොවන්නේ ඇයිද යන්න ශුන්‍යය තක්සේරු කිරීමට මම සැක කරමි ((var++)).
DreadPirateShawn

4
let var++උපුටා දැක්වීම් නොමැතිව භාවිතා කිරීම ආරක්ෂිතද ?
wjandrea

177
var=$((var + 1))

බාෂ් හි අංක ගණිතය $((...))සින්ටැක්ස් භාවිතා කරයි .


12
පිළිගත් පිළිතුරට වඩා බොහෝ සෙයින් හොඳයි. 10% ක ඉඩ ප්‍රමාණයක් තුළ, ඔබට ප්‍රමාණවත් උදාහරණ ලබා දීමට හැකි විය (එකක් ඕනෑ තරම් තිබේ - ඔබ පෙන්වන විට නවය ඉක්මවා යයි), සහ ((...))ගණිතය භාවිතා කිරීමේ යතුර එය බව දැන ගැනීමට ඔබ අපට ප්‍රමාණවත් තොරතුරු ලබා දී ඇත. කඩාවැටීමෙන්. පිළිගත් පිළිතුර දෙස බැලීමෙන් පමණක් බව මට වැටහුණේ නැත - මෙහෙයුම් අනුපිළිවෙල පිළිබඳ අමුතු නීති මාලාවක් හෝ පිළිගත් පිළිතුරෙහි සියලු වරහන් වලට තුඩු දෙන යමක් ඇතැයි මම සිතුවෙමි.
ArtOfWarfare

93

1 කින් වැඩි කිරීමට විවිධ විකල්ප, සහ කාර්ය සාධන විශ්ලේෂණය

විචල්ය බාෂ් වැඩි කිරීම සඳහා පහත දැක්වෙන ක්රම සපයන රාදු රාදේනුගේ පිළිතුරට ස්තූතියි :

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.


පෙනෙන විදිහට වේගය විධාන දිග සමඟ සම්බන්ධ වේ. විධාන එකම කාර්යයන් ලෙස හඳුන්වන්නේ දැයි මම කල්පනා කරමි.
මැතිව්රොක්

OP ඇසූ දේ නොවේ.
raygozag

@raygozag වර්ධක කරන්නේ කෙසේදැයි විමසීය. මගේ පිළිතුර පළමුව බොහෝ ක්‍රම ලැයිස්තුගත කරයි. දෘෂ්ටි කෝණයෙන් එය කෙලින්ම පිළිතුරු නොදෙන්නේ කෙසේද? ඉන්පසු එය එක් එක් ක්‍රමයට කාල තොරතුරු සපයයි. ඒ සියල්ල, ඔහු භාවිතා කිරීමට කැමති ක්‍රමය තෝරා ගැනීමට සහාය වීමට අමතර තොරතුරු පමණි.
කීත් රෙනෝල්ඩ්ස්

එයට දැනටමත් පිළිතුරු ලැබී ඇත, OP කාර්ය සාධන ඇගයීම් ඉල්ලා සිටියේ නැත, ඔබට කොතරම් ප්‍රයෝජනවත් වීමට අවශ්‍ය වුවත් ඔවුන් එය ඉල්ලා සිටියේ නැත.
raygozag

Bash 3.2.57 හි, ලූපයක් භාවිතා කිරීම declare -i xසහ පසුව කිරීම x+=1(වෙනත් දෙයක් කිරීම), xඑක් වරකට වඩා වැඩි නොවන බව මට පෙනී ගියේය . මෙම letසහ (())ක්රම දඩ වැඩ කළා.
ජෝන් ස්පෙන්සර්

18

මෙයද ඇත:

var=`expr $var + 1`

අවකාශයන් ගැන ප්‍රවේශමෙන් සටහන් කර ' එසේ නොවේ '

රාදුගේ පිළිතුරු සහ අදහස් පරිපූර්ණ හා ඉතා ප්‍රයෝජනවත් වුවද ඒවා විශේෂිත වේ. ඔබ විශේෂයෙන් බැෂ් ගැන විමසූ බව මම දනිමි, නමුත් මම සිතුවේ uCLinux යටතේ කාර්යබහුල පෙට්ටියේ sh භාවිතා කරමින් එකම දේ කිරීමට බලාපොරොත්තු වන විට මෙම ප්‍රශ්නය මට හමු වූ බැවින් මම එය නල කිරීමට සිතුවෙමි. මෙම අතේ ගෙන යා හැකි ය.


1
ඔබට ද භාවිතා කළ හැකියi=$((i+1))
wjandrea

ක්‍රියාවලි ආදේශනය $(...)මෙම කවචයේ තිබේ නම්, ඒ වෙනුවට එය භාවිතා කිරීමට මම නිර්දේශ කරමි.
රේඩන් රොස්බරෝ

10

ඔබ $varපූර්ණ සංඛ්‍යාවක් ලෙස ප්‍රකාශ කරන්නේ නම්, ඔබ පළමු වරට උත්සාහ කළ දෙය සැබවින්ම ක්‍රියාත්මක වනු ඇත:

$ declare -i var=5
$ echo $var
5
$ var=$var+1
$ echo $var
6

යොමුව: විචල්ය වර්ග, ආරම්භකයින් සඳහා බෑෂ් මාර්ගෝපදේශය


7

සියලුම පිළිතුරු වල එක් ක්‍රමයක් නොමැත - bc

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

bcPOSIX ප්‍රමිතියෙන් නියම කර ඇති බැවින් උබුන්ටු සහ POSIX- අනුකූල පද්ධතිවල සියලුම සංස්කරණවල තිබිය යුතුය. මෙම <<<හරවා යැවීමේ කිරීමට වෙනස් විය හැකි කළ 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

මෙහි වඩා හොඳ තේරීම් වලින් එකක් බරපතල ලෙස භාවිතා කරන්න.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.