[[và trường hợp tương đương trong bash


13

Làm

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

luôn cư xử giống như

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

hoặc có bất kỳ vấn đề nào không?


1
Tôi không thể tìm thấy bất kỳ trường hợp nào khác nhau, bất kể shoptcài đặt và giá trị trong $1hoặc pattern, $?sau đó. Sự khác biệt duy nhất $1là không được mở rộng ở đầu ra khi chạy bên dưới xtrace.
Kusalananda

Câu trả lời:


7

Vâng, họ (gần như) hoàn thành tương đương.


Chi tiết

Bên trong một [ … ]cấu trúc:

Các =nhà điều hành (hoặc thậm chí tùy chọn phi posix của ==) kiểm tra phù hợp với chuỗi, không phải mô hình phù hợp.

Bên trong một [[ ]]cấu trúc (từ man bash):

Khi các toán tử == và! = Được sử dụng, chuỗi bên phải của toán tử được coi là một mẫu và được khớp theo các quy tắc được mô tả bên dưới trong Kết hợp mẫu . Nếu tùy chọn shell nocasematch được bật, trận đấu được thực hiện mà không liên quan đến trường hợp các ký tự chữ cái. Giá trị trả về là 0 nếu chuỗi khớp với (==) hoặc không khớp với (! =) Mẫu và 1 nếu không. Bất kỳ phần nào của mẫu có thể được trích dẫn để buộc nó phải khớp với dạng chuỗi.

Bên trong một casecấu trúc (từ man bash, chỉnh sửa và nhấn mạnh của tôi):

trường hợp từ trong danh sách [[(] mẫu [| mẫu] ...) ;; ] ... esac
... lần lượt thử khớp nó với từng mẫu, sử dụng các quy tắc khớp giống như khi mở rộng tên đường dẫn (xem Mở rộng tên đường dẫn bên dưới). Tất cả các mẫu được kiểm tra đều được mở rộng bằng cách sử dụng mở rộng dấu ngã, mở rộng tham số và biến, thay thế số học, thay thế lệnh và thay thế quy trình. Nếu tùy chọn shell nocasematch được bật, trận đấu được thực hiện mà không liên quan đến trường hợp các ký tự chữ cái.

Cả hai Pattern MatchingPathname Expansionđược sử dụng để có nghĩa giống nhau trong hướng dẫn sử dụng bash.

Sự khác biệt duy nhất tôi có thể thấy trong hướng dẫn là:

`[[ … ]]`                                   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

Điều đó quote removalkhông được liệt kê rõ ràng cho trường hợp xây dựng.
Cái nào hoạt động để khớp chính xác cái này (cho cái [[ … ]]):

Bất kỳ phần nào của mẫu có thể được trích dẫn để buộc nó phải khớp với dạng chuỗi.

Sử dụng công cụ này để kiểm tra điểm cuối cùng này (bây giờ biến không phải là mẫu):

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

Tại sao gần như vậy?

  1. Ngụ ý extglob:

    Kể từ phiên bản 4.3 của bash

    Khi các toán tử '==' và '! =' Được sử dụng, chuỗi bên phải của toán tử được coi là một mẫu và được khớp theo các quy tắc được mô tả bên dưới trong Kết hợp mẫu, như thể tùy chọn shell extglob được bật .

    Điều đó có nghĩa là một mẫu được sử dụng với tùy chọn extglob hủy đặt sẽ hoạt động khác nhau trong câu lệnh tình huống và bên trong [[cấu trúc sau phiên bản bash 4.3.

  2. Ngụ ý |:

    Cú pháp cho trường hợp là:

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

    Điều đó có nghĩa là có thể có một vài mẫu được phân tách bằng |(OR).

    Như thế này:

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

    Cái nào sẽ khớp với một chuỗi chỉ các số hoặc chỉ các chữ cái trong abcde, như 1234hoặc aabee, nhưng không 12ahoặc b23.

    A [[sẽ hoạt động tương đương nếu regex (nhìn vào var p3) được sử dụng:

    #!/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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.