ความแตกต่างระหว่างเครื่องหมายเท่ากับเดียวและสองเท่า (=) ในการเปรียบเทียบเชลล์คืออะไร


28

อ่านว่าสำหรับการเปรียบเทียบสตริงภายในifเราจำเป็นต้องใช้วงเล็บสองตาราง =หนังสือบางเล่มกล่าวว่าการเปรียบเทียบที่สามารถทำได้โดย แต่มันใช้งานได้ดีด้วย==เช่นกัน

#!/bin/bash
a="hello"
b="world"
if [[ $a == $b ]];then
    echo "equal"
fi

มีความแตกต่างระหว่าง=และ==ในการเปรียบเทียบหรือไม่


4
ที่นี่มีคำถามไหม? ถ้าเป็นเช่นนั้นฉันไม่เห็นมัน สำหรับ= สำหรับ [==[[
Chris Down

@ChrisDown นั่นไม่จริงอย่างแน่นอน
xdavidliu

@xdavidliu สนใจที่จะทำอย่างละเอียด? แน่นอนมันเป็นความจริงตาม POSIX ซึ่งมีความเข้าใจไม่==ซึ่งเป็นเหตุผลที่คุณควรจะใช้=(ความเสมอภาค) ด้วย[และ==(จับคู่รูปแบบที่มีความหมายที่มีการอ้างทราบ) [[ด้วย ดูเทียบกับhelp test help [[
Chris Down

@ChrisDown บางทีฉันอาจเข้าใจผิดว่า "มีไว้เพื่อ" หาก "สำหรับ" หมายถึง "เท่านั้นทำงานร่วมกับ" จากนั้นแสดงความคิดเห็นไม่เป็นความจริงเนื่องจาก[ foo == foo ] && echo fooแน่นอนพิมพ์fooแสดงให้เห็นว่าทำงานร่วมกับ== [อย่างไรก็ตามถ้าโดย "สำหรับ" คุณหมายถึง "ตั้งใจที่จะใช้กับ" แล้วฉันมีการคัดค้านน้อย
xdavidliu

@xdavidliu "สำหรับ" ในกรณีเฉพาะที่คุณพูดถึงหมายความว่า "ถูกกำหนดโดย POSIX" เพียงเพราะทุบตียอมรับความสะดวกสบายไม่ได้หมายความว่าขอแนะนำ - ถ้าคุณละทิ้งการพกพาใช้เพียงแค่[[ในสถานที่แรกที่มีความเข้าใจที่เหมาะสมยิ่งขึ้นของ tokenisation การแยกคำ ฯลฯ ...
Chris Down

คำตอบ:


28

[[ $a == $b ]]ไม่ใช่การเปรียบเทียบมันเป็นการจับคู่รูปแบบ คุณต้องการ[[ $a == "$b" ]]การเปรียบเทียบความเท่าเทียมกันแบบ byte-to-byte =เหมือนกับ==ในเชลล์ใด ๆ ที่สนับสนุน[[...]](แนะนำโดยksh)

[[...]]ไม่ใช่shไวยากรณ์มาตรฐาน [ คำสั่งเป็นมาตรฐานและมาตรฐานการเปรียบเทียบผู้ประกอบการมี=(แม้บางคนจะ[ใช้งานยังตระหนัก==)

เช่นเดียวกับการโต้แย้งคำสั่งใด ๆ ตัวแปรจะต้องยกมาดังนั้น:

[ "$a" = "$b" ]

ในมาตรฐานการshจับคู่รูปแบบเสร็จสิ้นด้วยcase:

case $a in
  ($b) ...
esac

เพื่อความสมบูรณ์ผู้ดำเนินการที่มีลักษณะเหมือนเท่าเทียมกันอื่น ๆคุณอาจพบในสคริปต์เชลล์:

  • [ "$a" -eq "$b" ]: [ผู้ประกอบการมาตรฐานเพื่อเปรียบเทียบตัวเลขจำนวนเต็มทศนิยม [การใช้งานบางอย่างอนุญาตให้มีช่องว่างรอบ ๆ ตัวเลขบางตัวอนุญาตการแสดงออกทางคณิตศาสตร์โดยพลการ แต่นั่นไม่ใช่การพกพา portably หนึ่งสามารถใช้[ "$((a))" -eq "$((b))" ]สำหรับการที่ ดูเพิ่มเติม[ "$((a == b))" -ne 0 ]ที่จะเทียบเท่ามาตรฐาน (ยกเว้นว่า POSIXly พฤติกรรมที่ระบุเฉพาะถ้า$aและ$bมีค่าคงที่จำนวนเต็ม) ของ:
  • ((a == b))จาก ksh และยังพบในzshและbashผลตอบแทนจริงถ้าการประเมินผลของการแสดงออกทางคณิตศาสตร์ที่เก็บไว้ในอัตราผลตอบแทนหมายเลขเดียวกันกับที่ของ$a $bโดยทั่วไปแล้วจะใช้สำหรับการเปรียบเทียบตัวเลข โปรดทราบว่ามีความแตกต่างระหว่างเชลล์ว่าจะใช้วิธีการคำนวณนิพจน์ทางคณิตศาสตร์อย่างไรและได้รับการสนับสนุนตัวเลขใดบ้าง (เช่นอินสแตนซ์ทุบตีและการนำไปปฏิบัติบางรุ่น / ksh ไม่สนับสนุนทศนิยมหรือรักษาตัวเลขด้วยเลขศูนย์นำหน้า

  • expr "$a" = "$b"ทำการเปรียบเทียบตัวเลขถ้าตัวถูกดำเนินการทั้งสองจำได้ว่าเป็นเลขจำนวนเต็มฐานสิบ (บางตัวอนุญาตให้มีช่องว่างรอบ ๆ ตัวเลข) และตรวจสอบว่าตัวดำเนินการสตริงสองตัวมีลำดับการเรียงแบบเดียวกันหรือไม่ นอกจากนี้ยังจะล้มเหลวสำหรับค่า$aหรือ$bที่มีexprผู้ประกอบการต้องการ(, substr...

  • awk 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b": ถ้า$aและ$bจำได้ว่าเป็นตัวเลข (อย่างน้อยจำนวนเต็มทศนิยมและตัวเลขทศนิยมเช่น 1.2, -1.5e-4, ช่องว่างต่อท้ายนำหน้าจะถูกละเว้นบางคนก็จำเลขฐานสิบหกฐานแปดหรืออะไรก็ตามที่รู้จักstrtod()) แล้วทำการเปรียบเทียบตัวเลข มิฉะนั้นขึ้นอยู่กับการใช้งานมันเป็นทั้งการเปรียบเทียบสตริงไบต์ต่อไบต์หรือเช่นexprการstrcoll()เปรียบเทียบนั่นคือ$aและ$bเรียงลำดับเดียวกัน

ดูสิ่งนี้ด้วย:


13

สิ่งเหล่านี้เทียบเท่าในการทุบตี:

[[ $x == "$y" ]]
[[ $x = "$y" ]]
[ "$x" == "$y" ]
[ "$x" = "$y" ]

ตัวแปร $ x สองตัวแรกไม่จำเป็นต้องอ้างถึง Bash ทำการแยกคำและขยายชื่อพา ธ ภายใน [แต่ไม่อยู่ข้างใน [[:

$ x='a b'
$ [ -s $x ]
-bash: [: a: binary operator expected
$ [[ -s $x ]]
$ ls
$ [ a = * ]
-bash: [: a: unary operator expected
$ [[ a = * ]]
$ 

[[ $x = "$y" ]]เป็นการเปรียบเทียบสตริง แต่[[ $x = $y ]]เป็นการแสดงออกของการจับคู่รูปแบบ:

$ y='a*'; [[ aa = "$y" ]]; echo $?
1
$ y='a*'; [[ aa = $y ]]; echo $?
0

-eq มีไว้สำหรับใช้กับจำนวนเต็มเท่านั้น:

$ [[ x.x -eq x.x ]]
-bash: [[: x.x: syntax error: invalid arithmetic operator (error token is ".x")
$ x=9; [[ "x" -eq 9 ]]; echo $?
0

ดูเพิ่มเติมที่BashFAQ / 031: อะไรคือความแตกต่างระหว่างการทดสอบ [และ [[? .

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.