ฉันต้องการรู้ว่าอะไรคือความแตกต่างระหว่าง
a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )
4 ทั้งหมดกำหนดตัวแปร a ด้วย 2 แต่ความแตกต่างคืออะไร
จากสิ่งที่ฉันค้นพบจนถึงตอนนี้ก็คือ expr นั้นช้ากว่าเพราะมันไม่ใช่กระสุนจริงในตัว แต่ไม่มากกว่านั้น
ฉันต้องการรู้ว่าอะไรคือความแตกต่างระหว่าง
a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )
4 ทั้งหมดกำหนดตัวแปร a ด้วย 2 แต่ความแตกต่างคืออะไร
จากสิ่งที่ฉันค้นพบจนถึงตอนนี้ก็คือ expr นั้นช้ากว่าเพราะมันไม่ใช่กระสุนจริงในตัว แต่ไม่มากกว่านั้น
คำตอบ:
ข้อตกลงเหล่านี้ทั้งหมดเกี่ยวกับคณิตศาสตร์ แต่มีหลายวิธีและตัวแปรถูกสร้างขึ้นด้วยวิธีการที่ต่างกัน สิ่งเหล่านี้บางอย่างเป็นของbashเชลล์โดยเฉพาะ
$((...))เรียกว่าการขยายตัวทางคณิตศาสตร์ซึ่งเป็นเรื่องปกติของbashและkshเปลือกหอย สิ่งนี้ยอมให้ทำเลขคณิตเลขจำนวนเต็มอย่างง่ายโดยไม่มีจุดลอยตัว ผลลัพธ์ของนิพจน์จะแทนที่นิพจน์ดังที่echo $((1+1))จะเป็นecho 2((...))เรียกว่าการประเมินผลทางคณิตศาสตร์และสามารถใช้เป็นส่วนหนึ่งของif ((...)); thenหรือwhile ((...)) ; doงบ การขยายตัวทางเลขคณิต$((..))แทนการส่งออกของการดำเนินการและสามารถใช้ในการกำหนดตัวแปรในi=$((i+1))แต่ไม่สามารถใช้ในงบเงื่อนไข$[...] เป็นไวยากรณ์เก่าสำหรับการขยายเลขคณิตซึ่งเลิกใช้แล้ว ดูเพิ่มเติม สิ่งนี้อาจถูกเก็บไว้เพื่อไม่ให้bashสคริปต์เก่าแตก สิ่งนี้ใช้งานไม่ได้ksh93ดังนั้นฉันจึงคาดเดาว่าไวยากรณ์นี้เฉพาะสำหรับการทุบตี หมายเหตุ : ช่องว่างสำคัญมากที่นี่ อย่าสับสนกับสิ่งที่ชอบ$[1+1] [ $a -eq $b ]การ[เว้นวรรคเรียกว่าtestคำสั่งและโดยทั่วไปคุณจะเห็นมันในส่วนการตัดสินใจ มันแตกต่างกันมากในพฤติกรรมและวัตถุประสงค์letเป็น a bashและkshคำสำคัญที่ช่วยให้การสร้างตัวแปรที่มีการประเมินทางคณิตศาสตร์อย่างง่าย หากคุณพยายามที่จะกำหนดสตริงที่นั่นเหมือนlet a="hello world"คุณจะได้รับข้อผิดพลาดทางไวยากรณ์ ทำงานในและbashksh93$(...)คือการทดแทนคำสั่งโดยที่คุณรับเอาต์พุตของคำสั่งและกำหนดให้กับตัวแปรอย่างแท้จริง คำสั่งของคุณที่นี่คือexprซึ่งใช้อาร์กิวเมนต์ตำแหน่งเช่นexpr arg1 arg2 arg3ดังนั้นช่องว่างมีความสำคัญ มันเป็นเหมือนเครื่องคิดเลขบรรทัดคำสั่งขนาดเล็กสำหรับเลขจำนวนเต็มบวกกับบางสิ่งที่เป็นจริง / เท็จและ regex นี่คือคำสั่ง shell-neutralนอกจากนี้ยังเป็นที่น่าสังเกตว่าส่วนขยายทางคณิตศาสตร์และการแทนที่คำสั่งถูกระบุโดยมาตรฐาน POSIXในขณะที่letและ$[...]ไม่ใช่
letคำสั่งดำเนินการประเมินผลทางคณิตศาสตร์และเป็นเปลือกในตัว
เรียกใช้คำสั่งนี้และคุณจะไม่ได้รับอะไรเลย (ประเมินผลเท่านั้น):
let 1+2$(( ))ใช้เพื่อขยายเลขคณิต: อ่านที่นี่
เรียกใช้สิ่งนี้และคุณจะได้รับข้อผิดพลาด (เนื่องจากการขยาย):
$((1+2))$[ ] เป็นไวยากรณ์เก่าสำหรับการขยายเลขคณิต:
รูปแบบเก่า $ [expression] เลิกใช้แล้วและจะถูกลบออกเมื่อมีการทุบตี Bash Man Page
expr เป็นคำสั่งไบนารีหากคุณต้องการขยายเลขคณิตภายในสถานการณ์ย่อยคำสั่งคุณสามารถใช้มันได้:
echo $(expr 1 + 2)
echo `expr 1 + 2`เนื่องจากคำตอบบางข้อข้างต้นกล่าวถึงเป็นพิเศษksh93มันก็คุ้มค่าที่จะสังเกตว่ามันสามารถทำเลขทศนิยมได้เช่น:
$ print $((1.0/3))
0.333333333333333333
คุณสามารถควบคุมความแม่นยำของเอาต์พุตด้วย printf เช่น:
$ printf "%.4f\n" $((1.0/3))
0.3333
ต้องระบุอย่างน้อยหนึ่งอาร์กิวเมนต์เป็นตัวเลขทศนิยมดังกล่าวข้างต้น หากทั้งคู่ระบุว่าเป็นจำนวนเต็มจะมีการคำนวณทางคณิตศาสตร์เฉพาะจำนวนเต็มเช่น:
$ print $((1/3))
0
สิ่งนี้มีประโยชน์เมื่อคุณต้องการเลขทศนิยมในเชลล์สคริปต์เนื่องจากคุณสามารถหลีกเลี่ยงการเรียกคำสั่งภายนอก
zshkshbashzshkh93
letไม่ทำงานใน cron ฉันคิดว่าเป็นเพราะletมีสภาพแวดล้อมเป็นของตัวเอง ใช้$((...))เนื่องจากเป็น POSIX ตัวอย่างเช่น,
let x=1+2
echo x=$x
ใน cron ให้ผลลัพธ์เป็น "x =" แต่ "x = 3" เมื่อเรียกใช้จากเชลล์
x=$((1+2))
echo x=$x
ผลลัพธ์เป็น "x = 3" ในทุกกรณี
((...))จริงสามารถนำมาใช้สำหรับการมอบหมายงานในbash,kshและzsh:n=10; ((n+=10)); echo $nพิมพ์ 20 และ((x=1)); echo $xพิมพ์ 1.