ใครจะกรุณาอธิบายความแตกต่างระหว่าง-eq
และ==
ในการเขียนสคริปต์ทุบตี?
มีความแตกต่างระหว่างสิ่งต่อไปนี้หรือไม่?
[ $a -eq $b ]
และ [ $a == $b ]
มัน==
ใช้เฉพาะเมื่อตัวแปรมีตัวเลขหรือไม่?
ใครจะกรุณาอธิบายความแตกต่างระหว่าง-eq
และ==
ในการเขียนสคริปต์ทุบตี?
มีความแตกต่างระหว่างสิ่งต่อไปนี้หรือไม่?
[ $a -eq $b ]
และ [ $a == $b ]
มัน==
ใช้เฉพาะเมื่อตัวแปรมีตัวเลขหรือไม่?
คำตอบ:
เป็นอีกทางหนึ่ง: =
และ==
ใช้สำหรับการเปรียบเทียบสตริง-eq
สำหรับตัวเลข -eq
อยู่ในตระกูลเดียวกับ-lt
, -le
, -gt
, -ge
และ-ne
หากที่ช่วยให้คุณจำซึ่งเป็นที่
==
เป็น bash-ism โดยวิธีการ มันจะดีกว่าที่จะใช้ =
POSIX ในการทุบตีทั้งสองมีค่าเท่ากันและในรูปแบบ sh ธรรมดา=
เป็นสิ่งเดียวที่รับประกันว่าจะใช้งานได้
$ a=foo
$ [ "$a" = foo ]; echo "$?" # POSIX sh
0
$ [ "$a" == foo ]; echo "$?" # bash specific
0
$ [ "$a" -eq foo ]; echo "$?" # wrong
-bash: [: foo: integer expression expected
2
(หมายเหตุด้านข้าง: อ้างอิงการขยายตัวแปรเหล่านั้นอย่าทิ้งเครื่องหมายคำพูดคู่ไว้ด้านบน)
หากคุณกำลังเขียน#!/bin/bash
สคริปต์แล้วผมขอแนะนำให้ใช้[[
แทน รูปแบบทวีคูณมีคุณสมบัติมากขึ้นไวยากรณ์ที่เป็นธรรมชาติมากขึ้นและ gotcha น้อยลงที่จะพาคุณไป ไม่จำเป็นต้องมีเครื่องหมายคำพูดคู่อีกต่อไป$a
สำหรับหนึ่ง:
$ [[ $a == foo ]]; echo "$?" # bash specific
0
ดูสิ่งนี้ด้วย:
[[ $var = $pattern ]]
ถ้าคุณต้องการสิ่งที่มิฉะนั้นจะถูกตีความว่าเป็นรูปแบบ fnmatch ให้แทนจะตีความว่าเป็นสตริงตัวอักษร สตริงfoo
ไม่มีการตีความที่ไม่ใช่ตัวอักษรทำให้การออกคำพูดนั้นปลอดภัย เฉพาะในกรณีที่ OP ต้องการจับคู่ให้พูดfoo*
(โดยมีเครื่องหมายดอกจันเป็นตัวอักษรไม่ได้หมายถึงสิ่งใดก็ตามที่อยู่หลังสตริงfoo
) ที่จะต้องมีเครื่องหมายอัญประกาศหรือการหลีกเลี่ยง
[[
ได้อ้างถึงภายในเป็นการทุบตี (แสดงว่านั่นเป็นเหตุผลเดียวที่คุณไม่ได้ให้คำตอบ +1)
[ ... ]
==
: - /
ขึ้นอยู่กับโครงสร้างการทดสอบรอบตัวดำเนินการ ตัวเลือกของคุณ ได้แก่ วงเล็บปีกกาคู่วงเล็บปีกกาเดี่ยวหรือแบบทดสอบ
หากคุณใช้((... )) แสดงว่าคุณกำลังทดสอบส่วนของเลขคณิตด้วย==
ใน C:
$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1
(หมายเหตุ: 0
หมายถึงtrue
ในความรู้สึก Unix และไม่ใช่ศูนย์คือการทดสอบล้มเหลว)
การใช้-eq
ภายในวงเล็บคู่เป็นข้อผิดพลาดทางไวยากรณ์
หากคุณกำลังใช้[... ] (หรือรั้งเดียว) หรือ[[... ]] (หรือรั้งคู่) หรือtest
คุณสามารถใช้ -eq, -ne, -lt, -le, -gt หรือ -GE เป็นเปรียบเทียบเลขคณิต
$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0
==
ภายในวงเล็บเดียวหรือสองครั้ง (หรือtest
คำสั่ง) เป็นหนึ่งในผู้ประกอบการเปรียบเทียบสตริง :
$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1
ในฐานะตัวดำเนินการสตริง=
จะเทียบเท่า==
และสังเกตช่องว่างรอบ ๆ=
หรือที่==
ต้องการ
ในขณะที่คุณสามารถทำได้[[ 1 == 1 ]]
หรือ[[ $(( 1+1 )) == 2 ]]
กำลังทดสอบความเท่าเทียมกันของสตริง - ไม่ใช่ความเท่าเทียมทางคณิตศาสตร์
ดังนั้น-eq
การผลิตผลที่ได้อาจจะเป็นที่คาดว่าค่าจำนวนเต็มของ1+1
มีค่าเท่ากับ2
แม้ว่า RH เป็นสตริงและมีพื้นที่ต่อท้าย:
$ [[ $(( 1+1 )) -eq "2 " ]]; echo $?
0
ในขณะที่การเปรียบเทียบสตริงของสิ่งเดียวกันจะดึงพื้นที่ต่อท้ายและด้วยเหตุนี้การเปรียบเทียบสตริงจึงล้มเหลว:
$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1
และการเปรียบเทียบสตริงที่ผิดอาจทำให้ได้คำตอบที่ผิดทั้งหมด '10' เป็นศัพท์ที่น้อยกว่า '2' ดังนั้นการเปรียบเทียบสตริงจึงส่งกลับtrue
หรือ0
. หลายคนถูกกัดโดยข้อผิดพลาดนี้:
$ [[ 10 < 2 ]]; echo $?
0
เทียบกับการทดสอบที่ถูกต้องสำหรับ 10 เป็นเลขคณิตน้อยกว่า 2:
$ [[ 10 -lt 2 ]]; echo $?
1
ในความคิดเห็นมีคำถามเกี่ยวกับเหตุผลทางเทคนิคที่ใช้จำนวนเต็ม-eq
บนสตริงที่ส่งกลับค่า True สำหรับสตริงที่ไม่เหมือนกัน:
$ [[ "yes" -eq "no" ]]; echo $?
0
เหตุผลก็คือว่าทุบตีuntyped -eq
ทำให้เกิดสายที่จะตีความว่าเป็นจำนวนเต็มถ้าเป็นไปได้รวมถึงการแปลงฐาน:
$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0
และ0
ถ้า Bash คิดว่ามันเป็นเพียงสตริง:
$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1
ดังนั้น[[ "yes" -eq "no" ]]
จะเทียบเท่ากับ[[ 0 -eq 0 ]]
หมายเหตุสุดท้าย: ส่วนขยายเฉพาะ Bash จำนวนมากของ Test Constructs ไม่ใช่ POSIX ดังนั้นจะล้มเหลวในเชลล์อื่น ๆ เปลือกหอยอื่น ๆ โดยทั่วไปจะไม่สนับสนุน[[...]]
และ((...))
==
หรือ
[[ "yes" -eq "no" ]]
ส่งคืน True bash บังคับให้สตริงเหล่านี้เป็นค่าจำนวนเต็มที่สามารถเปรียบเทียบได้อย่างไร? ;-)
==
ในตัวอย่างโค้ดและมีเพียงการกล่าวถึง (แบบพกพา, มาตรฐาน) ที่=
อยู่ข้างใต้
==
เป็นนามแฝงเฉพาะ bash =
และทำการเปรียบเทียบสตริง (ศัพท์) แทนการเปรียบเทียบตัวเลข eq
เป็นการเปรียบเทียบตัวเลขแน่นอน
สุดท้ายฉันมักจะชอบใช้แบบฟอร์ม if [ "$a" == "$b" ]
==
ที่นี่เป็นรูปแบบที่ไม่ดีตาม=
ที่ POSIX ระบุเท่านั้น
==
แล้วนำมาใส่ในระหว่างและ[[
]]
(และตรวจสอบให้แน่ใจว่าบรรทัดแรกของสคริปต์ของคุณระบุให้ใช้/bin/bash
)
Guys: คำตอบหลายคำแสดงตัวอย่างอันตราย ตัวอย่างของ OP [ $a == $b ]
ใช้การแทนที่ตัวแปรที่ไม่มีเครื่องหมายคำพูดโดยเฉพาะ (แก้ไขเมื่อ ต.ค. 60) เพื่อ[...]
ความปลอดภัยสำหรับความเท่าเทียมกันของสตริง
แต่ถ้าคุณจะแจกแจงทางเลือกอื่นเช่น[[...]]
คุณต้องแจ้งด้วยว่าต้องยกมาทางขวามือ ถ้าไม่ยกมาแสดงว่าเป็นแพทเทิร์นเป๊ะ! (จากหน้า bash man: "ส่วนใดส่วนหนึ่งของรูปแบบอาจถูกยกมาเพื่อบังคับให้จับคู่เป็นสตริง")
ในการทุบตีสองคำสั่งที่ให้ "ใช่" คือการจับคู่รูปแบบอีกสามรายการคือความเท่าเทียมกันของสตริง:
$ rht="A*"
$ lft="AB"
$ [ $lft = $rht ] && echo yes
$ [ $lft == $rht ] && echo yes
$ [[ $lft = $rht ]] && echo yes
yes
$ [[ $lft == $rht ]] && echo yes
yes
$ [[ $lft == "$rht" ]] && echo yes
$
[ "$lht" = "$rht" ]
มีคำพูดที่น่าเชื่อถือแม้เพื่อความเท่าเทียมกัน หากคุณมีแฟ้มที่สร้างขึ้นด้วยtouch 'Afoo -o AB'
, [ $lft = $rht ]
จะกลับจริงแม้ว่าชื่อไฟล์ที่เป็นไม่ได้เลยAB
ที่จะเหมือนกัน
[[
รวมแล้วเป็น ksh-ism ยุค 1980 ที่นำมาใช้ (และเปลือกหอยอื่น ๆ อีกมากมาย) นั่นคือจุดรวม - ถ้าคุณมี[[
เลยคุณสามารถสันนิษฐานได้อย่างปลอดภัยว่าส่วนขยายทั้งหมดที่ใช้งานอยู่รอบ ๆ นั้น (fnmatch()
- การจับคู่รูปแบบสไตล์, นิพจน์ทั่วไปของ ERE=~
และใช่การปราบปรามการแยกสตริงและการโกลบระบบไฟล์) จะเป็น ใช้ได้ เนื่องจาก[[
เป็นไวยากรณ์ที่ไม่ใช่ POSIX โดยสิ้นเชิงจึงไม่มีการสูญเสียความสามารถในการพกพาเพิ่มเติมโดยสมมติว่าคุณลักษณะที่เกิดขึ้นจะพร้อมใช้งาน