GNU/Linux >> Znalost Linux >  >> Linux

Jak používat proměnnou jako případovou podmínku?

Snažím se použít proměnnou skládající se z různých řetězců oddělených | jako case výrokový test. Například:

string=""foo"|"bar""
read choice
case $choice in
    $string)
        echo "You chose $choice";;
    *)
        echo "Bad choice!";;
esac

Chci umět psát foo nebo bar a spusťte první část case prohlášení. Nicméně oba foo a bar vezmi mě na druhou:

$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!

Pomocí "$string" místo $string nedělá žádný rozdíl. Ani použití string="foo|bar" .

Vím, že to mohu udělat takto:

case $choice in
    "foo"|"bar")
        echo "You chose $choice";;
    *)
        echo "Bad choice!";;
esac

Napadají mě různá řešení, ale rád bych věděl, zda je možné použít proměnnou jako case stav v bash. Je to možné, a pokud ano, jak?

Přijatá odpověď:

Bash manuál uvádí:

velká a malá písmena v seznamu [ [(] vzor [ | vzor ] … );; ] … esac

Každý zkoumaný vzor je rozšířen pomocí rozšiřování vlnovky, rozšiřování parametrů a proměnných, aritmetické substituce, substituce příkazů a substituce procesu.

Žádné «rozšíření názvu cesty»

Tedy:vzor NENÍ rozšířen pomocí «Rozšíření názvu cesty».

Proto:vzor NEMŮŽE obsahovat „|“ uvnitř. Pouze:dva vzory lze spojit pomocí „|“.

Toto funguje:

s1="foo"; s2="bar"    # or even s1="*foo*"; s2="*bar*"

read choice
case $choice in
    $s1|$s2 )     echo "Two val choice $choice"; ;;  # not "$s1"|"$s2"
    * )           echo "A Bad  choice! $choice"; ;;
esac

Pomocí « Extended Globbing »

Nicméně word odpovídá pattern pomocí pravidel « Expanze názvů ».
A « Rozšířené globování » zde, zde a zde umožňuje použití alternujících (“|”) vzorů.

Toto také funguje:

shopt -s extglob

string='@(foo|bar)'

read choice
    case $choice in
        $string )      printf 'String  choice %-20s' "$choice"; ;;&
        $s1|$s2 )      printf 'Two val choice %-20s' "$choice"; ;;
        *)             printf 'A Bad  choice! %-20s' "$choice"; ;;
    esac
echo

Obsah řetězce

Další testovací skript ukazuje, že vzor odpovídá všem řádkům, které obsahují buď foo nebo bar kdekoli je '*$(foo|bar)*' nebo dvě proměnné $s1=*foo* a $s2=*bar*

Testovací skript:

shopt -s extglob    # comment out this line to test unset extglob.
shopt -p extglob

s1="*foo*"; s2="*bar*"

string="*foo*"
string="*foo*|*bar*"
string='@(*foo*|*bar)'
string='*@(foo|bar)*'
printf "%sn" "$string"

while IFS= read -r choice; do
    case $choice in
        "$s1"|"$s2" )   printf 'A first choice %-20s' "$choice"; ;;&
        $string )   printf 'String  choice %-20s' "$choice"; ;;&
        $s1|$s2 )   printf 'Two val choice %-20s' "$choice"; ;;
        *)      printf 'A Bad  choice! %-20s' "$choice"; ;;
    esac
    echo
done <<-_several_strings_
f
b
foo
bar
*foo*
*foo*|*bar*
"foo"
"foo"
afooline
onebarvalue
now foo with spaces
_several_strings_

Linux
  1. Jak používat BusyBox na Linuxu

  2. Jak používat příkazy historie Bash

  3. Jak používám cron v Linuxu

  1. Jak používat FIND v Linuxu

  2. Jak používat Nginx k přesměrování

  3. Jak používat Su Command v Linuxu

  1. Jak provést nepřímé vyhodnocení proměnných?

  2. jak používat pylint ve vim

  3. Jak používat dos2unix?