bash: teste, ob $ WORD in der Menge

ist. Ich suche nach einem Konstrukt in bash, um zu entscheiden, ob Eine Variable $WORD ist eines der definierten Wörter. Ich brauche so etwas:

if "$WORD" in dog cat horse ; then echo yes else echo no fi 

hat bash ein solches Konstrukt? Wenn nicht, welche wäre die nächste?

Antwort

Dies ist eine reine Bash-Lösung (> = Version 3) verwendet reguläre Ausdrücke:

if [[ "$WORD" =~ ^(cat|dog|horse)$ ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi 

Wenn Ihre Wortliste lang ist, können Sie sie in einer Datei speichern (ein Wort pro Zeile) und dies tun:

if [[ "$WORD" =~ $(echo ^\($(paste -sd"|" /your/file)\)$) ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi 

Eine Einschränkung beim Dateiansatz:

  • Es wird unterbrochen, wenn die Datei Leerzeichen enthält. Dies kann behoben werden durch:

    sed "s/[[:blank:]]//g" /your/file | paste -sd "|" /dev/stdin 

Vielen Dank an @terdon, der mich daran erinnert hat, das Muster ordnungsgemäß mit ^ und $.

Kommentare

  • Und shopt -s nocasematch kann hilfreich sein, wenn bei der Suche die Groß- und Kleinschreibung nicht berücksichtigt werden soll.
  • Beachten Sie, dass Sie [[ und ]][ und ] reichen nicht aus.
  • Ich habe gesucht für einen ‚ Oneliner ‚, um mein Skriptargument zu validieren, und dies funktionierte perfekt. Danke! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
  • Wenn Sie ‚ Ihre Liste der Übereinstimmungen in eine Datei einfügen möchten, können Sie diese auch verwenden grep: egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK".

Antwort

case $word in dog|cat|horse) echo yes;; *) echo no;; esac 

Antwort

Wie wäre es mit:

#!/usr/bin/env bash WORD="$1" for w in dog cat horse do if [ "$w" == "$WORD" ] then yes=1 break fi done; [ "$yes" == "1" ] && echo "$WORD is in the list" || echo "$WORD is not in the list" 

Dann:

$ a.sh cat cat is in the list $ a.sh bob bob is not in the list 

Antwort

if (echo "$set" | fgrep -q "$WORD") 

Kommentare

  • Vorsicht, dies gibt true zurück, wenn $WORD leer ist, stimmt es überein, wenn WORD=ca oder WORD=og oder ähnliches und ich nehme an, Sie meinten echo ${set[@]}.
  • fügen Sie einfach hinzu -w zu grep, um Teilwörter zu vermeiden

Antwort

Sie können hierfür eine Bash-Funktion definieren:

function word_valid() { if [ "$1" != "cat" -a "$1" != "dog" -a "$1" != "horse" ];then echo no else echo yes fi } 

Verwenden Sie dann einfach Folgendes:

word_valid cat 

Antwort

Ich suchte nach einer „einzeiligen“ Lösung, um mein Skriptargument zu validieren, und verwendete oben die Antwort Joseph R. up with:

[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }

Antwort

Sie Mit fgrep können alle zulässigen Wörter angegeben werden:

if $(echo "$WORD" | fgrep -wq -e dog -e cat -e horse) ; then echo yes else echo no fi 

Das Flag -w stimmt nur mit vollständigen Wörtern überein, das -q bewirkt, dass es unbeaufsichtigt arbeitet (da wir nur den Rückgabewert für die zu verwendende if-Anweisung benötigen), und jedes -e -Muster gibt ein Muster an

fgrep ist die Version von grep, die normale Zeichenfolgenübereinstimmung anstelle von Regex-Übereinstimmungen ausführt. Wenn Sie grep haben, sollten Sie fgrep haben. Wenn nicht, ist dies identisch mit der Verwendung von grep durch das Flag -F (Sie würden also einfach fgrep -wq oben durch grep -Fwq).

Antwort

Dies hat bei mir funktioniert:

#!/bin/bash phrase=(cat dog parrot cow horse) findthis=parrot for item in ${phrase[*]} do test "$item" == "$findthis" && { echo "$findthis found!"; break; } done 

Antwort

Möglicherweise möchten Sie die Liste der Wörter in eine Datei einfügen, falls Sie die Liste häufig ändern oder möchten Sie müssen die Wörter möglicherweise in eine Datei einfügen, wenn die Liste zu lang wird, um sie in einem Skript zu verwalten. Dann können Sie

if fgrep –qx "$WORD" word_list 

Kommentare

  • Nein, ich ‚ möchte meine Liste nicht in einer Datei haben

Antwort

Wenn Wörter eine Liste sind, in der Werte durch einen Zeilenumbruch getrennt sind, können Sie Folgendes tun:

WORDS="$(ls -1)" if echo "${WORDS}" | grep --quiet --line-regexp --fixed-strings "${WORD}"; then echo yes else echo no fi 

Antwort

Ich hatte gerade das gleiche Problem und fand eine überraschend verständliche Lösung, für die keine Regex-Kenntnisse erforderlich sind.

Bitte beachten Sie, dass die Die unten gezeigte Lösung ist möglicherweise nur Bash, da ich keine Ahnung habe, welche Unterschiede zwischen Bash und anderen Shells bestehen. Darüber hinaus warnt das Bash-Handbuch, dass diese Art der Musterübereinstimmung langsam ist, wenn die Zeichenfolge, die abgeglichen werden soll, lang ist.

WORD=abc [[ "$WORD" == @(def|abc|ghi|foo|barbaz) ]] && echo Word is in set. 

Wie funktioniert das?Ich möchte hier keine großen Teile des Bash-Handbuchs wiederholen, aber in meinen eigenen Worten:

Wenn der binäre Operator == mit dem zusammengesetzten Befehl verwendet wird [[, das Wort auf der rechten Seite des Operators wird einem Mustervergleich unterzogen, wie im Abschnitt “ Mustervergleich im Bash-Handbuch. Außerdem wird unter diesen Bedingungen beim Matching angenommen, dass die Shell-Option extglob festgelegt ist (unabhängig von der tatsächlichen Einstellung) Der entscheidende Punkt für das Verständnis des oben Gesagten.

Aber was ist, wenn die Wörter in Ihrem Satz bereits Zeichen enthalten, die eine besondere Bedeutung für den Mustervergleich, die Befehlssubstitution und andere Erweiterungen haben? Das Mittel ist einfach: Verwenden Sie einfach so etwas wie

[[ "$WORD" == @("a*"|abc|"?ghi"|"$DontExpandMe"|barbaz) ]] && echo Word is in set. 

Ich fand das sehr einfach, verständlich und effizient (solange $WORD kurz ist) Lösung, die keine Nebenwirkungen hat oder da ist wie die set -basierten Methoden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.