Вопрос по switch-statement, pattern-matching, bash – Использование переменной в качестве шаблона в Bash

20

Я пытаюсь написать сценарий Bash, который использует переменную в качестве шаблона в выражении case. Однако я просто не могу заставить его работать.

Изложение дела: я

case "$1" in
    $test)
        echo "matched"
        ;;
    *)
        echo "didn't match"
        ;;
esac

мы пробовали это с назначением$test как , ,aaa|bbb|ccc(aaa|bbb|ccc)[aaa,bbb,ccc] и несколько других комбинаций. Я также попробовал это как образец в заявлении дела:@($test)@($(echo $test))$($test), Также нет успеха.

РЕДАКТИРОВАТЬ

Для ясности я бы хотел, чтобы переменная представляла несколько шаблонов, например:

case "$1" in
    aaa|bbb|ccc)
        echo "matched"
        ;;
    *)
        echo "didn't match"
        ;;
esac

Ваш Ответ

3   ответа
3

обновленный): Вот'С чем-то немного по-другому, но я надеюсь, что это работает для того, что вам нужно:

#!/bin/bash

pattern1="aaa bbb ccc"
pattern2="hello world"
test=$(echo -e "$pattern1\n$pattern2" | grep -e $1)

case "$test" in
    "$pattern1")
        echo "matched - pattern1"
        ;;
    "$pattern2")
        echo "matched - pattern2"
        ;;
    *)
        echo "didn't match"
        ;;
esac

Это используетgrep сделать сопоставление с шаблоном для вас, но все же позволяет вам указать несколько наборов шаблонов, которые будут использоваться в структуре оператора case.

Например:

  • Если либо,aaabbb, или жеccc это первый аргумент скрипта, он будет выводиться.matched - pattern1
  • Если либоhello или жеworld это первый аргумент, это будет выводить.matched - pattern2
  • В противном случае это будет выводить.didn't match
это может сработать, если $ 1 - это aaa, а не для bbb и ccc. Guru
@ Гуру прав. Это соответствует только первый, так какtest становится.aaa siebz0r
@ siebz0r обновленный ответ - посмотрите, работает ли это для вас. sampson-chen
19

Вы можете использоватьextglob опция:

#! /bin/bash

shopt -s extglob         # enables pattern lists like +(...|...)
test='+(aaa|bbb|ccc)'

for x in aaa bbb ccc ddd ; do
    echo -n "$x "
    case "$x" in
        $test) echo Matches.
        ;;
        *) echo Does not match.
    esac
done
Это круто! Спасибо! @anubhava Почему ваше предложение будет лучше (@ вместо +)? siebz0r
+1 за напоминание об использованииextglob, Кстатиtest='@(aaa|bbb|ccc)'также работает и, вероятно, является лучшим вариантом в этом случае. anubhava
@anubhava Неважно, нашел егоВот, @ соответствует одному вхождению, + соответствует нескольким. ( siebz0r
1

Использование Eval также работает:

eval 'case "$1" in

    '$test')
        echo "matched"
        ;;
    *)
        echo "did not match"
        ;;
esac'

Похожие вопросы