10
votes

Shell correspondant à un motif à l'aide d'une déclaration de cas qui est stockée dans une variable

J'essaie de faire correspondre un modèle avec une déclaration de casse où le motif est stocké à l'intérieur d'une variable. Voici un exemple minimal: xxx

malheureusement le "|" semble être échappé (intéressant "*" ou "?" ne sont pas). Comment puis-je obtenir cela pour travailler, c'est-à-dire correspondre à "FOO"? J'ai besoin de stocker le motif dans une variable car elle est construite de manière dynamique. Cela doit fonctionner sur une coquille compatible POSIX.


1 commentaires

Merci pour toutes les suggestions, mais je ne peux pas compter sur les outils Bash ou GNU, cela doit fonctionner sur un environnement de coquillage POSIX . Je voulais utiliser une construction de cas pour éviter un si impressionnant "foo \ n" | grep -e -q "$ {motif}" 2> / dev / null; Alors ... d'autre ... FI Pour des raisons de performances (Subshell + Fourche) car je ferais un modèle de shell et je iTerai sur ce code plusieurs fois chanceux. J'étais simplement surpris que cela ne fonctionnait pas.


7 Réponses :


1
votes

Votre modèle est en fait une liste de motifs et le séparateur | doit être donné littéralement. Votre seule option semble être eval . Cependant, essayez d'éviter cela si vous le pouvez.


2 commentaires

Je suis d'accord - vous pouvez utiliser EVAL mais c'est le chemin de la folie.


L'ensemble doit être dans la déclaration eval (c'est pourquoi c'est la folie); Il y a un exemple donné ici: Stackoverflow.com/a/38153401/248390



0
votes

Certaines versions de Expr code> (par exemple GNU) permettent une correspondance de modèle avec alternance. xxx pré>

sinon, j'utiliserais un outil comme AWK: P> xxx pré>

ou plus contrariété: p> xxx

Vous pouvez l'utiliser comme ceci: P>

PATTERN="foo|bar|baz"
VALUE=oops
matches() { awk -v v="$1" -v p="$2" 'BEGIN {exit !(v~p)}'; }
if matches "$VALUE" "$PATTERN"; then
    echo match
else
    echo no match
fi


0 commentaires

3
votes

Cela devrait fonctionner:

PATTERN="foo|bar|baz|bla"

shopt -s extglob

case "foo" in
    @($(echo $PATTERN)))
        printf "matched\n"
        ;;
    *)
        printf "no match\n"
        ;;
esac


3 commentaires

Vous n'avez pas besoin du $ (echo) juste faire @ ($ motif)


Est-ce un posixisme ou est-ce qu'un bashisme? J'ai regardé dans la page de la cendre et je n'ai pas vu cette structure, mais je n'ai pas non plus lu chaque lettre.


shopt n'est clairement pas POSIX ; Voir aussi page de Greycat sur le sujet .



0
votes

Vous pouvez utiliser la correspondance REGEX dans BASH:

PATTERN="foo|bar|baz|bla"

if [[ "foo" =~ $PATTERN ]]
then
    printf "matched\n"
elif . . .
    . . .
elif . . .
    . . .
else
    printf "no match\n"
fi


0 commentaires

1
votes

"Vous ne pouvez pas y arriver d'ici"

J'aime en utilisant un étui pour le motif correspondant, mais dans cette situation, vous passez au-delà du bord de ce que Bourne Shell est bon pour. P>

là sont deux hacks pour résoudre ce problème: p>

au détriment d'une fourchette, vous pouvez utiliser EGREP P>

pattern="this|that|those"

IFS="|" temp_pattern="$pattern"
echo=echo

for value in $temp_pattern
do
  case foo 
  in
    "$list") echo "matched" ; echo=: ; break ;;
  esac
done
$echo not matched


0 commentaires

-1
votes

Cela évite la nécessité de s'échapper ou de toute autre chose: xxx


0 commentaires

5
votes

Il est possible de faire correspondre une sous-chaîne dans une chaîne sans reproduire un sous-processus (tel que grep code>) à l'aide des seules méthodes compatibles POSIX de s (1p) code> , tel que défini dans Section 2.6.2, expansion des paramètres .

Voici une fonction de commodité: P>

PATTERN="|foo bar|baz|bla|"

case "$needle" in
    xyz) echo "matched in a static part" ;;
    *)
        if [ -z "${PATTERN##*|${needle}|*}" ]; then
            echo "$needle matched $PATTERN"
        else
            echo "not found"
        fi
esac


0 commentaires