[[і еквівалентність випадку в баш


13

Чи

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

завжди поводитись так само, як

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

чи є якісь готчі?


1
Я не можу знайти жодних випадків, коли вони різняться, незалежно від shoptналаштувань і значень у, $1або patternні $?згодом. Єдина відмінність полягає в тому, що $1він не розширюється у виході під час роботи під xtrace.
Kusalananda

Відповіді:


7

Так, вони (майже) повністю рівнозначні.


Деталь

Всередині [ … ]конструкції:

=Оператор (або навіть варіант не-POSIX з ==) перевіряє відповідність рядка, а не відповідає шаблон.

Всередині [[ ]]конструкції (від man bash):

Коли використовуються оператори == і! =, Рядок, що знаходиться праворуч від оператора, вважається шаблоном і узгоджується відповідно до правил, описаних нижче в розділі Узгодження шаблону . Якщо опція оболонки nocasematch увімкнена, збіг виконується без огляду на регістр буквених символів. Повернене значення дорівнює 0, якщо рядок відповідає (==) або не відповідає (! =) Шаблону, а 1 - інакше. Будь-яка частина шаблону може бути цитована, щоб змусити його відповідати як рядок.

Всередині caseконструкції (з man bash, відредагований та наголошений мін):

слово слова у списку [[(] шаблону [| шаблону] ...) ;; ] ... esac
... намагається по черзі співставити його з кожним шаблоном, використовуючи ті самі правила відповідності, що і для розширення імені шляху (див. Розширення Pathname нижче). … Кожен досліджуваний візерунок розширюється за допомогою розширення тильди, розширення параметрів та змінних, арифметичної підстановки, підстановки команд та заміни процесу. Якщо опція оболонки 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 bash

    Коли використовуються оператори '==' і '! =', Рядок праворуч від оператора вважається шаблоном і узгоджується відповідно до правил, описаних нижче в Шаблоні узгодження, як ніби включена опція оболонки extglob .

    Це означає, що шаблон, який використовується з опцією extglob unset, буде працювати по-різному в операторі випадку і всередині [[конструкції після bash версії 4.3.

  2. Неявне |:

    Синтаксис case:

    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, але не, 12aабо b23.

    A [[буде працювати еквівалентно, якщо використовується регулярний вираз (дивіться на 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.