Je reçois une chaîne qui peut être entièrement numérique séparée par des tirets, et dans ce cas, elle est acceptable pour moi (par exemple 123423-56788-456522-34245 ) ou pas tous numériques et toujours séparés par des tirets, et dans ce cas, ce n'est pas acceptable pour moi (par exemple 123423-56788-shelve-34245 ).
Afin de déterminer si la chaîne est acceptable ou non, j'ai construit le bloc if suivant:
-bash: 123423-56788-shelve-34245 =~ ^[0-9-]+$: attempted assignment to non-variable (error token is "=~ ^[0-9-]+$")
Le bloc if ci-dessus fonctionne correctement. Cependant, si je programmais dans un autre langage (par exemple, Java), j'attribuerais l'évaluation directement dans la variable. Par exemple:
InvalidCL=123423-56788-shelve-34245
MyRegex='^[0-9-]+$'
FalseExpression=$((${InvalidCL} =~ ${MyRegex}))
Le test ci-dessus serait true : j'évaluerais l'expression ( a ) et stockez son résultat dans la variable test sur une seule ligne.
Je voudrais savoir s'il est possible de faire la même chose dans Bash. En parcourant le Web, je n'ai pas trouvé beaucoup d'exemples. Grâce à cette réponse , j'ai réalisé que si je le fais ceci:
bash$ false_expression=$((2 == 4)) bash$ true_expression=$((2 == 2))
... les deux variables prennent respectivement les valeurs 0 et 1 . Ce n'est pas exactement true ou false , mais je pourrais toujours l'accepter.
Cependant, je ne semble pas être capable de faire la même chose avec mon expression car si je fais ceci:
int a = 3; int b = 5; boolean test = (a < b);
... la troisième affectation soulève cette erreur: p>
REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS='^[0-9-]+$'
if [[ ${BUILD_ID} =~ ${REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS} ]]
then
echo true
else
echo false
fi
Je ne suis pas un vrai expert en bash, donc ma question (en espérant que ce ne soit pas trop idiot) est: est-il possible d'attribuer l'évaluation à une variable? em> Je peux voir que mon if [[myExpression]] est évalué comme true , donc je ne comprends pas pourquoi je ne pourrais pas attribuer cette évaluation à une variable ... Quelqu'un peut-il expliquer s'il vous plaît?
4 Réponses :
Si vous voulez vraiment le faire avec un devoir, vous pouvez le faire comme:
$ [[ "$InvalidCL" =~ $MyRegex ]] $ FalseExpression=$?
où 1 signifie true et 0 pour false . Gardez à l'esprit, cependant, que ce n'est pas la méthode traditionnelle Bash. Un résultat de 0 dans Bash n'indique aucune erreur, c'est-à-dire que si l'expression est évaluée à true alors vous obtenez un statut de sortie de:
$ echo $? 0
Pas besoin de && ou || ; juste $ ([[...]]; echo $?) suffira.
@chepner Oui, mais OP a posté: true_expression = $ ((2 == 2)) d'où j'ai conclu qu'il voulait qu'un 1 indique true code>, d'où les opérateurs conditionnels pour attribuer la valeur "appropriée".
Bon point. Cela dépend du contexte dans lequel FalseExpression sera utilisé.
Merci pour votre réponse nautique. J'aime l'approche, mais si je définis ValidCL = 123423-56788-456522-34245 puis exécutez TrueExpression = $ ([["$ ValidCL" = ~ "$ MyRegex"]] && echo 1 || echo 0) , la valeur de TrueExpression sera toujours 0 alors qu'elle est supposée être 1 . Même chose avec la deuxième solution que vous avez montrée :(
P.s. Je clarifie: peu importe si l'expression est vraie ou fausse, elle affichera toujours le même résultat. Il ne s'agit pas de basculer le 0 et le 1 (j'ai compris qu'ici nous suivons le succès - 0 - ou l'échec - 1).
@MatteoNNZ Désolé, mon mal. Ne mettez PAS de guillemets autour de $ MyRegex . Voir mon message mis à jour.
@nautical maintenant ça marche, merci. J'attendrai un peu plus pour voir si de nouvelles réponses se présenteront, puis je choisirai ma préférée. Mais un +1 est en tout cas bien mérité tant pour les solutions que pour les explications :)
Fini pour ça, c'est clair, une seule ligne et surtout facilement personnalisable de 0/1 à vrai / faux ce que je voulais :)
Vous pouvez également faire:
[[ ${BUILD_ID} =~ ${REGEX_FOR_ONLY_NUMERICAL_CHANGELISTS} ]]
val=$?
pour éviter d'appeler un sous-shell. Encore une fois, val est 0 en cas de succès et 1 en cas d'échec.
val = $? Bash ne permet pas d'espace avant et après le = .
Comme l'a commenté la réponse de Paul, même vos travaux sont bons, mais je trouve cela un peu difficile à comprendre pour un premier lecteur du code. J'attendrai un peu pour voir si d'autres réponses montrent une solution plus claire avant d'accepter une réponse, mais un +1 est mérité :)
Si vous souhaitez une attribution directe sur une seule ligne à un booléen numérique, vous pouvez utiliser un opérateur "non" dans votre test.
Je fortement vous recommande d'ajouter quelques commentaires explicatifs à ce sujet.
boolMatch() {
local match str="$1" pat="$2"
# test the match
[[ "$str" =~ $pat ]]
# invert the return to a boolean value
match=$(( ! $? ))
# pass back the boolean
echo $match
}
$: boolMatch foo bar
0
$: boolMatch foo foo
1
$: match=$( boolMatch $stringToCheck $patternToUse )
Pour plus de clarté, créez une fonction contenant les commentaires pour encapsuler la logique et appelez cela à partir d'une ligne.
# assign an integer BOOLEAN value from the test for a match # the ! means NOT, inverts a 0/1 OS exit code from [[ ]] match="$( [[ ! "$string" =~ $pattern ]]; echo $?; )" # now $match is 1 (TRUE) if it *matched* the pattern
Cela fonctionne très bien. Cependant, comme vous le dites, c'est un peu difficile à comprendre pour un premier lecteur du code. J'attendrai un peu pour voir si d'autres réponses montrent une solution plus claire avant d'accepter une réponse, mais un +1 est mérité :)
J'ai eu encore quelques minutes, alors j'ai élargi ma réponse. :)
Merci Paul, très apprécié. Je vais aller avec l'autre réponse juste parce que je trouve plus clair à lire pour quelqu'un d'autre touchant le code, mais c'est aussi très gentil, merci!
D'autres ont déjà montré comment contourner l'obtention de la valeur de retour booléenne de la correspondance d'expression régulière.
En ce qui concerne la formulation de la question réelle, je tiens à souligner que les résultats de l'évaluation d'une expression regex sont en fait automatiquement stockés dans une variable d'environnement dans bash. Le tableau $ BASH_REMATCH stocke la correspondance entière à l'index 0 et les groupes de capture à leurs index respectifs. Voir: https://www.linuxjournal.com/content/bash-regular-expressions < / a>
Le nombre d'éléments dans ce tableau peut aussi, peut-être plus confortablement que l'affectation manuelle de $? , être utilisé comme indicateur de succès de la correspondance. Si $ {# BASH_REMATCH [*]} vaut zéro, la dernière expression régulière ne correspond pas.
Vous obtenez le message d'erreur que vous avez cité car la syntaxe de correspondance des expressions régulières est définie uniquement dans la construction [[...]] , pas dans $ ((...)) < / code> évaluation arithmétique, donc quand il voit le = il pense que vous devez essayer une sorte d'affectation.
C'était la première réponse que j'ai lancée. :RÉ