[[และกรณีเทียบเท่าในทุบตี


13

ทำ

if [[ "$1" = pattern ]]; then
    hook
fi

ประพฤติเช่นเดียวกับเสมอ

case "$1" in
    pattern) hook;;
esac

หรือมี gotchas ใด ๆ


1
ฉันไม่พบกรณีใด ๆ ที่มีความแตกต่างไม่ว่าจะมีshoptการตั้งค่าและค่าต่าง ๆ ใน$1หรือpatternไม่$?ก็ตาม แต่ที่แตกต่างก็คือว่าจะไม่ได้ขยายในการส่งออกเมื่อทำงานภายใต้$1 xtrace
Kusalananda

คำตอบ:


7

ใช่พวกเขา (เกือบ) เทียบเท่าที่สมบูรณ์


รายละเอียด

ภายใน[ … ]โครงสร้าง:

ตัว=ดำเนินการ (หรือแม้แต่ตัวเลือกที่ไม่ใช่ posix ของ==) ทดสอบการจับคู่สตริงไม่ใช่การจับคู่รูปแบบ

ภายใน[[ ]]โครงสร้าง (จากทุบตีคน):

เมื่อ == และ! = ผู้ประกอบการมีการใช้สตริงไปทางขวาของผู้ประกอบการที่มีการพิจารณารูปแบบและจับคู่ให้เป็นไปตามกฎระเบียบที่ระบุไว้ด้านล่างภายใต้รูปแบบการจับคู่ หากเปิดใช้งานตัวเลือกเชลล์nocasematchการจับคู่จะดำเนินการโดยไม่คำนึงถึง ตัวอักษรพิมพ์ใหญ่ ค่าที่ส่งคืนคือ 0 ถ้าสตริงตรงกับ (==) หรือไม่ตรงกับ (! =) รูปแบบและ 1 เป็นอย่างอื่น ส่วนใดส่วนหนึ่งของรูปแบบอาจถูกยกมาเพื่อบังคับให้จับคู่เป็นสตริง

ภายในcaseโครงสร้าง (จากการทุบตีคนแก้ไขและเน้นทุ่นระเบิด):

กรณีคำในรายการ [[(] รูปแบบ [| รูปแบบ] ... ) รายการ ;; ] ... esac
... พยายามจับคู่กับแต่ละรูปแบบโดยใช้กฎการจับคู่แบบเดียวกันกับการขยายชื่อพา ธ (ดูที่การขยายชื่อพา ธด้านล่าง) …แต่ละรูปแบบการตรวจสอบจะถูกขยายโดยใช้การขยายตัวของตัวหนอนการขยายพารามิเตอร์และตัวแปรการแทนที่ทางคณิตศาสตร์การแทนที่คำสั่งและการทดแทนกระบวนการ หากเปิดใช้งานตัวเลือกเชลล์nocasematchการจับคู่จะดำเนินการโดยไม่คำนึงถึงตัวอักษรพิมพ์ใหญ่

ทั้งสองPattern MatchingและPathname Expansionใช้เพื่อหมายถึงสิ่งเดียวกันภายในคู่มือทุบตี

ข้อแตกต่างที่ฉันเห็นในคู่มือคือ:

`[[ … ]]`                                   case
tilde  expansion                            tilde expansion
parameter and variable expansion            parameter and variable expansion
arithmetic expansion                        arithmetic substitution
command substitution                        command substitution
process substitution                        process substitution
quote removal

ที่quote removalไม่ได้ระบุไว้อย่างชัดเจนสำหรับการสร้างกรณี
ซึ่งทำงานเพื่อให้ตรงกับสิ่งนี้ (สำหรับ[[ … ]]):

ส่วนใดส่วนหนึ่งของรูปแบบอาจถูกยกมาเพื่อบังคับให้จับคู่เป็นสตริง

ใช้สิ่งนี้เพื่อทดสอบจุดสุดท้าย (ตอนนี้ตัวแปรไม่ใช่รูปแบบ):

case "$1" in
  "$pattern") echo case match
esac

ทำไมถึงเกือบ

  1. โดยนัยextglob:

    ตั้งแต่เวอร์ชั่น 4.3 ของการทุบตี

    เมื่อ '==' และ '! =' ผู้ประกอบการมีการใช้สตริงไปทางขวาของผู้ประกอบการที่มีการพิจารณารูปแบบและจับคู่ตามกฎที่ระบุไว้ด้านล่างในรูปแบบการจับคู่เป็นตัวเลือกถ้า extglob เปลือกถูกเปิดใช้งาน

    นั่นหมายความว่ารูปแบบที่ใช้กับตัวเลือกextglob unsetจะทำงานแตกต่างกันในคำสั่ง case และภายใน[[โครงสร้างหลังจาก bash เวอร์ชัน 4.3

  2. โดยนัย|:

    ไวยากรณ์สำหรับเคสคือ:

    case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac

    ซึ่งหมายความว่าอาจมีหลายรูปแบบคั่นด้วย|(หรือ)

    แบบนี้:

    shopt -s extglob;      p1="+([0-9])";       p2="+([abcde])"
    
    case "$1" in
        $p1|$p2)    echo "or case match" ; ;;
    esac
    

    ซึ่งจะตรงกับทั้งสตริงของตัวเลขหรือตัวอักษรเพียงเฉพาะในabcdeเหมือน1234หรือaabeeแต่ไม่ได้หรือ12ab23

    A [[จะทำงานได้อย่างเท่าเทียมกันหากใช้regex (ดูที่ var p3):

    #!/bin/bash
    
    shopt -s extglob           ### Use extended globbing.
    shopt -s globasciiranges   ### The range [a-z] will expand to [abcdefghijklmnopqrstuvwxyz].
    
    pattern="+([0-9])"
    p1="+([0-9])"
    p2="+([a-z])"
    p3="^([0-9]+|[a-z]+)$"
    
    case "$1" in
        $pattern)   echo case1 match ; ;&
        $p1|$p2)    echo case2 match ; ;;
    esac
    
    [[ "$1" == $pattern ]] && echo if1 match
    [[ "$1" =~ $p3 ]] && echo if2 match
    
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.