ใครจะกรุณาอธิบายความแตกต่างระหว่าง-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 โดยสิ้นเชิงจึงไม่มีการสูญเสียความสามารถในการพกพาเพิ่มเติมโดยสมมติว่าคุณลักษณะที่เกิดขึ้นจะพร้อมใช้งาน