So negieren Sie reguläre Ausdrücke mithilfe von Test

So negieren Sie reguläre Ausdrücke mithilfe von Test

Das ist syntaktisch falsch:

#!/usr/bin/env bash

dimension="4x5"

if [[ "$dimension" !=~ '[0-9]x[0-9]' ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 return 1;
fi

die obige Syntax ist falsch...also meine Frage ist - gibt es eine Möglichkeit,!=~

...ich vermute, es ist !~? Wenn das stimmt, so viel zu Negationsregeln, lulz. Okay, ich habe es getestet und es !~funktioniert auch nicht.

Antwort1

Für das Schlüsselwort gibt es keine !=~Oder- Operatoren . Stattdessen wird das Ergebnis des Vergleichs negiert:!~[[

[[ ! "string" =~ regex ]]

Zum Zitieren des regexArguments heißt es im Handbuch:

Jeder Teil des Musters kann in Anführungszeichen gesetzt werden, um die Übereinstimmung des zitierten Teils als Zeichenfolge zu erzwingen.

Daher sollten Teile von regulären Ausdrücken regexnicht in Anführungszeichen gesetzt werden – es sei denn, die Shell-Option compat31ist gesetzt:

shopt...compat31

Wenn gesetzt, ändert bash sein Verhalten in Bezug auf zitierte Argumente des Operators [[des bedingten Befehls auf das der Version 3.1=~

Versuchen Sie für das angegebene Beispiel:

if [[ ! "$dimension" =~ ^[0123456789]+x[0123456789]+$ ]]; then
    printf '%s %s\n' "'$dimension'" 'is not a valid dimension.'
fi
  • regexsollte mit verankert werden ^...$, andernfalls foo1x1fubarwürde es als gültige Dimension betrachtet werden.

Denken Sie auch daran, keine Bereiche wie für die Eingabevalidierung zu verwenden 0-9, insbesondere wenn es um die Bereinigung in sicherheitsrelevanten Kontexten geht, da diese Bereiche in vielen Gebietsschemas viel mehr Zeichen enthalten (oder möglicherweise aus mehreren Zeichen bestehende Sortierelemente) als früher (und im Gebietsschema C/POSIX immer noch tun).

Für hilft 's =~hier nicht. Unter Ubuntu 19.10 und in der Locale finde ich, dass 's zusätzlich zu 0123456789 mit oder ohne 1040 verschiedenen Zeichen übereinstimmt . Zumindest in meinem Fall haben sie alle eine Beziehung zu den Dezimalziffern 0 bis 8, aber das ist nicht einmal allgemein garantiert.bashglobasciirangesen_GB.UTF-8bash[0-9]globasciiranges

Andererseits stimmt [[:digit:]]und [0123456789]nur mit diesen 10 überein und sollte auf jedem POSIX-kompatiblen System übereinstimmen.

shSie können dies auch mithilfe der Standardsyntax und Platzhaltermustern tun, etwa mit:

valid_geometry() case $1 in
  (*[!x0123456789]* | *x | x* | *x*x*) false;;
  (*x*) true;;
  (*) false;;
esac
if ! valid_geometry "$dimension"; then
   ...
fi

Oder mit KSH-Globs (wie auch von bash -O extglobund bashsogar [[ohne unterstützt extglob) mit:

if [[ $dimension != +([0123456789])x+([0123456789]) ]]; then
  ...
fi

Antwort2

Okay, das scheint zu funktionieren:

if [[ ! "$dimension" =~ [0-9]+x[0-9]+ ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

aber ich frage mich, warum das Einschließen in einfache Anführungszeichen nicht funktioniert:

if [[ ! "$dimension" =~ '[0-9]+x[0-9]+' ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

hier ist meine Lösung:

dimension="3x5"

regex='[0-9]+x[0-9]+'

if [[ ! "$dimension" =~ $regex ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

Jetzt können Sie einfache Anführungszeichen verwenden, um den regulären Ausdruck zu zitieren, aber Sie müssen die doppelten Anführungszeichen vermeiden, wenn Sie innerhalb von [[ ]] auf $regex verweisen. Ich bin jedoch immer noch neugierig, ob es eine Abkürzung für [0-9]+.. gibt.

verwandte Informationen