2011-01-14 9 views
0

Ich versuche herauszufinden, wie eine dynamische Case-Anweisung in einem Bash-Skript erstellen.Dynamische Case-Anweisung in Bash

Zum Beispiel lassen Sie uns sagen, dass ich die Ausgabe eines awk-Anweisung haben mit folgendem Inhalt

red 
green 
blue 

In diesem Szenario kann die Ausgabe jederzeit ändern.

Ich versuche dann verschiedene Logik auszuführen, wenn ein Wert in dieser awk-Ausgabe enthalten ist.

Also, wenn die Daten über in $ Liste enthalten ist, dann würde ich konzeptionell wie etwas tun mögen:

case "${my_var}" in 
    $list) 
     ..... 
    something_else) 
     ..... 
esac 

Ich versuche, diese zu verwenden, um eine dynamische benutzerdefinierte Tabulatorvervollständigung Funktion zu bauen (siehe http://www.debian-administration.org/article/An_introduction_to_bash_completion_part_2 für etwas Hintergrund).

Irgendwelche Ideen?

Danke.

+2

Die interessante Frage ist: "Wie werden Sie spezifizieren, was in dem ..... Teil des Falles für jede der Aktionen geht?" –

Antwort

3

Eine case Anweisung ist wahrscheinlich nicht das richtige Werkzeug für den Job. Wenn Sie die Ausgabe awk in einem Array speichern, können Sie das Array durchlaufen, um festzustellen, ob eine Auswahl darin enthalten ist, und als Bonus können Sie herausfinden, um welchen Index es sich handelt.

#!/bin/bash 

# Store command output in an array so each word is a separate array item.  
list=($(echo $'red\ngreen\nblue')) 
my_var=blue 

for ((i = 0; i < ${#list}; i++)); do 
    if [[ ${list[$i]} = $my_var ]]; then 
     echo "found at index $i" 
     break 
    fi 
done 

if ((i == ${#list})); then 
    echo "not found" 
fi 
2

Sie können dies nicht mit einer case-Anweisung tun, aber es ist einfach genug, einen eigenen Helfer einzurichten, um nach einer Listenmitgliedschaft zu suchen.

# stub to simulate this arbitrary call 
my_awk_command() { printf '%s\n' red green blue; } 
# helper to check list membership 
list_contains() { 
    local tgt="$1"; shift 
    while (($#)); do 
    if [[ $1 = "$tgt" ]] ; then 
     return 0 
    fi 
    shift 
    done 
    return 1 
} 

# the below is Bash 4 functionality; see BashFAQ #1 on how to replace it 
readarray -t awk_output < <(my_awk_command) 

if list_contains "$my_var" "${my_awk_command[@]}"; then 
    ...something... 
elif [[ "$my_var" = something_else ]] ; then 
    ...something else... 
fi 
1

Sie können dies von verschiedenen hacky Weise in ein paar nähern:

pattern=($(awk_command))  # red\ngreen\nblue\n 
saveIFS=$IFS 
IFS='|' 
pattern="^(${pattern[*]})$" # ^(red|green|blue)$ (perhaps hackish) 
IFS=$saveIFS 

# simple regex match if statement (not hackish) 
if [[ $var =~ $pattern ]] 
then 
    do_something 
fi 

# or a backwards case statement (very hackish) 
case 1 in # this could be a variable or a command substitution 
    $([[ $var =~ $pattern]] && echo 1)) # the echo 1 could be another command or the 1 could be yet another variable 
     do_something;; 
    *) 
     do_default;; 
esac 
2

Sie eine dynamische Case-Anweisung in bash die folgenden, indem Sie erstellen: gewährleisten

1) die Liste ist PIPE (|) getrennt. IE. rot | grün | blau

2) wickeln Sie Ihre Case-Anweisung in einem eval

Zum Beispiel:

valid="red|green|blue" 

eval "case \"$choice\" in 
    $valid) 
     echo do something good here 
     ;; 
    *) 
     echo invalid colour 
     ;; 
esac" 

Dieses für einfache variable Verarbeitung funktioniert, kann ich nicht garantieren, dies in allen Fällen funktionieren.