Bash-Skript zum Überprüfen, ob die Eingabe ein @ hat

Bash-Skript zum Überprüfen, ob die Eingabe ein @ hat

Hallo, ich versuche, ein Bash-Skript zu schreiben, in dem die Eingabe überprüft wird, um festzustellen, ob sie ein @-Symbol enthält. Ich bin relativ neu bei Bash, also verzeihen Sie mir bitte alle Fehler! Bisher habe ich:

var1="@"
var2="INPUT"

echo "input"
read INPUT

if [[ "$var2" == "$var1" ]]; then
echo "pass"
else
echo "fail"
fi

Antwort1

Obwohl Sie die Möglichkeit haben, die eingebaute Shell-Funktionalität zu verwenden, um zu prüfen, ob die Eingabe des Benutzers enthalten ist @(was in den anderen Antworten gut dokumentiert ist), ist eine andere sinnvolle Möglichkeit, dies zu tun, die externegrepDienstprogramm:

#!/usr/bin/env bash

read -erp '> '
if grep -q @ <<<"$REPLY"; then
    echo pass
else
    echo fail
fi

Durch Übergeben des -qFlags grepwird verhindert, dass übereinstimmende Zeilen gedruckt werden. (Es verhindert auch, dass nach dem Finden einer Übereinstimmung weitere Zeilen gelesen werden, aber das macht hier keinen Unterschied, da nur eine Eingabezeile vorhanden ist.)

ifEs ist verlockend, die Konstruktion auf etwas wie abzukürzen grep -q @ <<<"$REPLY" && echo pass || echo fail, aber ich habe dies bewusst vermieden:

  • In diesem Fall, das ist wahrscheinlich in Ordnung, da das falsche Wort nur dann gedruckt wird, wenn es passeigentlich gedruckt werden sollte und echonicht gedruckt wurde. Dann würde vermutlich failauch echo nicht gedruckt.
  • Während Kurzschluss &&und ||oft selbst angemessen sind (und ich benutze sie häufig, um einenif ohneeine elseKlausel), wobei sie zusammen verwendet werden, als obein ternäresWennOperatorist nicht wirklich eine gute Angewohnheit. Während einige Befehle nichtscheitern,echo dürfen.
  • Wenn der BenutzerWeiterleitungendie Ausgabe Ihres Skripts in eine nicht beschreibbare Datei oder auf ein nicht beschreibbares Gerät oder verwendet es in einem defektenPipeline, Echo und andere Befehle, die Text ausgeben, können Fehler zurückgeben, wodurch der &&Ausdruck fehlschlägt und die rechte Seite des ||Ausdrucks ausgeführt wird.
  • Sie können das Verhalten eines Skripts bei Vorhandensein eines nicht beschreibbaren Ausgabegeräts testen, indem Sie es mit ausführen >/dev/full.

Dieses Skript verwendet einige Bash-Funktionen:

  • -eaktiviert GNU Readline, sodass der Benutzer den Cursor mit den Pfeiltasten nach links und rechts bewegen kann, um seine Eingabe während der Eingabe zu bearbeiten.
  • In Bash readwird die Benutzereingabe automatisch in die REPLYVariable eingefügt, wenn keine Variable angegeben wurde.
  • Ahier Zeichenfolgemit <<<ist eine praktische Möglichkeit, die Benutzereingaben an weiterzuleiten grep.
  • Bash undmancheandere Shells im Bourne-Stil wie dash accept -p. AberPOSIX-kompatible Shells müssen nur verstehen-r. Und in manchen Fällen, wie zum Beispiel ksh, -phat es eine andere Bedeutung.
    (Danke angeirhafür den Hinweis, dass-pfehlt manchmalund dasEs bedeutet nicht immer „prompt“.)

Wenn Sie ein Skript wünschen, das auf andere Betriebssysteme portierbar ist, auf denen Bash möglicherweise nicht installiert ist, können Sie Folgendes verwenden:

#!/bin/sh

printf '> '
read -r line

if printf '%s' "$line" | grep -q @; then
    echo pass
else
    echo fail
fi

Wenn Sie möchten, können Sie das Speichern der Benutzereingaben in einer Variablen überspringen, indem Sie sie mitheadanstatt read:

#!/bin/sh

printf '> '
if head -1 | grep -q @; then
    echo pass
else
    echo fail
fi

AlsGeirha erwähnt, head -n 1könnte als bessere Syntax angesehen werden, wie head -1sie istoffiziell veraltet(obwohl aktuelle sedImplementierungen oder zumindest GNU sed -1in ihren neuesten Versionen dies unterstützen, während einige sehr alte sedImplementierungen dies nicht unterstützen -n 1).

Alsdie headDokumentationsagt, Sie können sedstattdessen für maximale Portabilität verwenden.

#!/bin/sh

printf '> '
if sed 1q | grep -q @; then
    echo pass
else
    echo fail
fi

Antwort2

Dieser bashCode liest die Eingabe und signalisiert „Pass“, wenn die Eingabe ein @Symbol enthält:

read -p "Input: " var
[ "${var//[^@]/}" ] && echo Pass || echo Fail

Anmerkungen:

  • [ "$var" ]ist ein Bash-Test. Er gibt „true“ zurück, wenn die Zeichenfolge $varnicht leer ist.

  • Eine der Funktionen von Bash ist die Musterersetzung. Es sieht aus wie ${var//pattern/string}. Es ersetzt jedes Vorkommen von patternin vardurch string. In unserem Fall patternist [^@]dies ein regulärer Ausdruck, der auf jedes Zeichen passtaußer @. Gibt daher ${var//[^@]/}einen leeren String zurück, sofern nicht varmindestens ein enthalten ist @.

  • Wir kombinieren die beiden oben genannten:

    [ "${var//[^@]/}" ]
    

    Dieser Test ist nur erfolgreich, wenn ${var//[^@]/}nicht leer ist, und ${var//[^@]/}nur dann nicht leer, wenn varmindestens ein enthält @.

Verwenden eines expliziten if-then-else:

read -p "Input: " var
if [ "${var//[^@]/}" ]
then
    echo Pass
else
    echo Fail
fi

POSIX-Shell

Folgendes funktioniert unter dash( /bin/sh) und sollte unter jeder POSIX-Shell funktionieren:

printf "Input: "
read var
case "$var" in
    *@*) echo Pass
        ;;
    *) echo Fail
        ;;
esac

Die POSIX-Shell unterstützt nicht die -pOption,read. Stattdessen wird also eine Kombination aus printfund readverwendet. Da außerdem die erweiterten Variablenerweiterungsfunktionen von fehlen , kann bashdie Anweisung für Glob-Matching verwendet werden.case

Android Shell

Mit der Standard-Shell auf meinem Android funktioniert Folgendes:

echo -n "Input: "; read var
if ! [ "${var//@/}" = "$var" ]
then
    echo Pass
else
    echo Fail

Antwort3

In Bash wird die Mustervergleichsfunktion von bevorzugt [[ ... ]].

#bash
read -rp "Input: " input
if [[ $input = *@* ]]; then
    printf '<%s> contains @\n' "$input"
fi

Für shSkripte können Sie casestattdessen verwenden.

#sh
printf 'Input: '
read -r input
case $input in
    *@*) printf '<%s> contains @\n' "$input" ;;
esac

Siehe auch dieTests und BedingungenKapitel des Bash-Handbuchs.

Antwort4

In neueren Versionen von Bash sollten Sie in der Lage sein, einenÜbereinstimmung mit regulären Ausdrückenüber den =~erweiterten Testoperator:

$ read -p "input: " input
input: quertyuiop 
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
no match
$ 
$ read -p "input: " input
input: qwerty@uiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
match

Eine Alternative, die in jedem POSIX-kompatiblen System funktionieren sollte, ist exprbeispielsweise die Verwendung in der dashShell:

$ read input
qwertyuiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
no match
$ 
$ read input
qwerty@uiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
match
$ 

verwandte Informationen