ฉันจะทำการหารด้วยตัวแปรในเชลล์ลินุกซ์ได้อย่างไร


143

เมื่อฉันเรียกใช้คำสั่งในเชลล์ของฉันดังต่อไปนี้จะส่งคืนexpr: non-integer argumentข้อผิดพลาด ใครช่วยอธิบายเรื่องนี้ให้ฉันฟังหน่อยได้ไหม

$ x=20
$ y=5
$ expr x / y 
expr: non-integer argument

4
@ShivanRaptor ในขณะที่บางคนอาจโต้แย้งว่าคำถามเป็นคำถาม RTFM แต่ก็เป็นคำถามการเขียนโปรแกรมเชลล์ที่ถูกต้อง นอกจากนี้ยังเป็นคำถามที่สมเหตุสมผลสำหรับผู้ที่มาจากภาษาที่ไม่ต้องการการอ้างอิง (เช่น Ruby หรือ JavaScript) ควรเปิดทิ้งไว้
Todd A.Jacobs

6
@ShivanRaptor ไม่นี่คือหัวข้อที่นี่ มันเกี่ยวกับการเขียนโปรแกรมใน Bash Unix / Linux มีไว้สำหรับการใช้งานระบบเป็นหลักไม่ใช่การเขียนโปรแกรม ตอนนี้เชลล์สคริปต์ครอบคลุมขอบเขตระหว่างการเขียนโปรแกรมและการใช้ระบบดังนั้นสิ่งนี้อาจอยู่ในหัวข้อบนไซต์ใดไซต์หนึ่ง หากมีคำถามเกี่ยวกับ "ฉันจะตั้งค่าระบบเครือข่ายได้อย่างไร" นั่นจะเป็นของ Unix / Linux แน่นอน หากเป็นคำถามเกี่ยวกับการเชื่อมโยงคีย์แบบโต้ตอบใน Bash นั่นก็จะอยู่ที่นั่นเช่นกัน แต่คำถามเกี่ยวกับเชลล์สคริปต์ก็มีอยู่ในหัวข้อนี้เช่นกัน
Brian Campbell

ดูคำตอบของฉันที่นี่ซึ่งแสดงให้เห็นถึงการลบและการหารตัวแปร $ BASH โดยใช้การเรียก Python จากเชลล์ (เพื่อแปลง int เป็น float ... ): stackoverflow.com/questions/8385627/…
Victoria Stuart

คำตอบ:


203

ตัวแปรเหล่านั้นคือตัวแปรเชลล์ ในการขยายเป็นพารามิเตอร์ไปยังโปรแกรมอื่น ( เช่น expr ) คุณต้องใช้$คำนำหน้า:

expr $x / $y

สาเหตุที่บ่นเป็นเพราะคิดว่าคุณพยายามใช้งานตัวอักษร ( เช่นไม่ใช่จำนวนเต็ม)

หากคุณใช้ Bash shell คุณสามารถบรรลุผลลัพธ์เดียวกันได้โดยใช้ไวยากรณ์ของนิพจน์:

echo $((x / y))

หรือ:

z=$((x / y))
echo $z

1
คุณสามารถหาข้อมูลได้มากมายโดยการอ่าน man-page สำหรับ bash พิมพ์man bashที่พร้อมท์ ( qเพื่อออก)
ข้าวเปลือก

67
จะต้องมีการสังเกตบางแห่งในหน้านี้ว่าเชลล์ GNU / Linux ส่วนใหญ่ (ถ้าไม่ใช่ทั้งหมด) จะดำเนินการเฉพาะจำนวนเต็มเท่านั้น
Skippy le Grand Gourou

39

ฉันเชื่อว่ามีการกล่าวถึงในหัวข้ออื่นแล้ว:

calc(){ awk "BEGIN { print "$*" }"; }

จากนั้นคุณสามารถพิมพ์:

calc 7.5/3.2
  2.34375

ในกรณีของคุณจะเป็น:

x=20; y=3;
calc $x/$y

หรือหากคุณต้องการเพิ่มสิ่งนี้เป็นสคริปต์แยกต่างหากและทำให้พร้อมใช้งานใน $ PATH ดังนั้นคุณจะมีอยู่ในเชลล์ในเครื่องของคุณเสมอ:

#!/bin/bash
calc(){ awk "BEGIN { print $* }"; }

5
คุณสามารถใช้echo '1 / 3' | bc -l
ยูจีน

20

ทำไมไม่ใช้ let; ฉันพบว่ามันง่ายกว่ามาก นี่คือตัวอย่างที่คุณอาจพบว่ามีประโยชน์:

start=`date +%s`
# ... do something that takes a while ...
sleep 71

end=`date +%s`
let deltatime=end-start
let hours=deltatime/3600
let minutes=(deltatime/60)%60
let seconds=deltatime%60
printf "Time spent: %d:%02d:%02d\n" $hours $minutes $seconds

อีกตัวอย่างง่ายๆ - คำนวณจำนวนวันตั้งแต่ปี 1970:

let days=$(date +%s)/86400

15

การอ้างอิงตัวแปร Bash ต้องการการขยายพารามิเตอร์

เชลล์เริ่มต้นในการกระจาย Linux ส่วนใหญ่คือ Bash ในทุบตีตัวแปรต้องใช้คำนำหน้าเครื่องหมายดอลลาร์สำหรับการขยายตัวพารามิเตอร์ ตัวอย่างเช่น:

x=20
y=5
expr $x / $y

แน่นอนว่า Bash ยังมีตัวดำเนินการทางคณิตศาสตร์และไวยากรณ์การขยายเลขคณิตพิเศษดังนั้นจึงไม่จำเป็นต้องเรียกใช้ไบนารีexprเป็นกระบวนการแยกต่างหาก คุณสามารถปล่อยให้เชลล์ทำงานทั้งหมดดังนี้:

x=20; y=5
echo $((x / y))

1
ดูการขยายเลขคณิตและเลขคณิตของเชลล์ในคู่มืออ้างอิง Bash สำหรับรายละเอียดที่เต็มไปด้วยเลือดทั้งหมด
Todd A.Jacobs

1
สิ่งนี้ไม่เกี่ยวข้องกับการอ้างอิงแต่เป็นการสอดแทรกและexprท้อใจในปี 2013
Gilles Quenot

@sputnick คุณสับสนอย่างชัดเจน โปรดปรึกษาพจนานุกรม ดูdereferenceและตีความ
Todd A.Jacobs

1
คำที่ดีกว่ากำลังขยายออก แต่ไม่ใช่การอ้างถึง dereferencingถูกใช้เมื่อเราใช้พอยน์เตอร์ไม่ใช่ในกรณีนี้นั่นเป็นเพียงตัวแปรง่ายๆ
Gilles Quenot

1
@Prashant: tldp ไม่เป็นที่รู้จักในการอ้างอิงที่ดีในโลกแห่งการทุบตี
Gilles Quenot

2

หากต้องการรับตัวเลขหลังจุดทศนิยมคุณสามารถทำได้: -

read num1 num2
div=`echo $num1 / $num2 | bc -l`
echo $div

1

สมมติว่า

x=50
y=5

แล้ว

z=$((x/y))

สิ่งนี้จะทำงานได้อย่างถูกต้อง แต่ถ้าคุณต้องการใช้ / ตัวดำเนินการในกรณีที่คำสั่งไม่สามารถแก้ไขได้ ใส่รหัสที่นี่ ในกรณีนั้นให้ใช้สตริงง่ายๆเช่น div หรือ dev หรืออย่างอื่น ดูรหัส


นี่เป็นสิ่งที่ไม่ถูกต้อง /ใช้งานได้ดีเหมือนฉลากเคสเชลล์ สิ่งที่ใช้ไม่ได้คือการใช้*เพื่อคูณโดยไม่ต้องอ้างถึงซึ่งอาจเป็นสิ่งที่คุณทำจริง ที่ทำให้สามารถแทนที่รายการต่อไปนี้ทั้งหมดในกรณีนี้ได้อย่างมีประสิทธิภาพซึ่งในตัวอย่างของคุณคือ 'devide' และ 'modulo'
dave_thompson_085
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.