#1 Le 27/02/2009, à 12:24
- Flo45
Bash : test d'un caractere
Bonjour,
Voila je fais un peu de scripting en bash, et je suis confronter à un probleme sur le test d'un caractere, je m'explique :
j'ai une variable X, qui contient un caractere (numérique ou alphanumérique).
Et donc j'aimerais tester cette variable qui contient le caractere et si la variable contient un numérique, on fait le traitement Y mais si la variable contient de l'alphanumérique on fait le traitement Z.
Voila j'espere que j'ai été assez clair
Merci d'avance pour votre aide
#2 Le 27/02/2009, à 12:45
- alexduf
Re : Bash : test d'un caractere
Bonjour,
Un chouilla de google t'aurais rapidement amené ici : http://www.commentcamarche.net/faq/sujet-4605-shell-tester-une-variable-numerique
Bonne lecture ;-)
Hors ligne
#3 Le 27/02/2009, à 14:33
- Totor
Re : Bash : test d'un caractere
http://www.commentcamarche.net/faq/sujet-4605-shell-tester-une-variable-numerique
Il existe aussi une solution Bash native (puisqu'il s'agit bien de Bash) :
#!/bin/bash
function testCaractere
{
UN_CARACTERE="$1"
echo -n "${UN_CARACTERE} est "
[[ "${UN_CARACTERE}" =~ [[:digit:]] ]] && echo "numérique" || echo "non numérique";
}
testCaractere "A"
testCaractere "5"
Dans tous les cas, on peut écrire une fonction de la sorte :
#!/bin/bash
function estNumerique
{
[[ "$1" =~ [[:digit:]] ]]
return $?
}
if estNumerique "A"; then echo "A est numerique"; else echo "A est non numérique"; fi
if estNumerique "5"; then echo "5 est numerique"; else echo "5 est non numérique"; fi
-- Lucid Lynx --
Hors ligne
#4 Le 27/02/2009, à 18:21
- quimporte
Re : Bash : test d'un caractere
inutile de recourir à =~
function estNumerique
{
[[ "$1" = [0-9] ]]
}
estNumerique "A" && echo "A est numerique" || echo "A est non numérique"
estNumerique "5" && echo "5 est numerique" || echo "5 est non numérique"
#5 Le 27/02/2009, à 21:07
- Totor
Re : Bash : test d'un caractere
inutile de recourir à =~
function estNumerique { [[ "$1" = [0-9] ]] } estNumerique "A" && echo "A est numerique" || echo "A est non numérique" estNumerique "5" && echo "5 est numerique" || echo "5 est non numérique"
c'est vrai...
j'avais en tête l'ER [[:digit:]]\+ qui nécessitait le tild.
-- Lucid Lynx --
Hors ligne
#6 Le 03/03/2009, à 02:03
- cristobal78
Re : Bash : test d'un caractere
pour alexduf
le 1er exemple sur Comment ca marche ... ne marche pas, même en supprimant les blancs entre les [ [ et les ] ]
D'ailleurs pourquoi les avoir mis ??? si c'est pour qu'on les enlève.
Qu'on mette 314 ou toto le résultat est le même.
Laptop Lenovo Ubuntu 20.04 LTS / DELL Mint 20.2 - XFCE / Laptop HP Mint 20.2 - XFCE
Hors ligne
#7 Le 03/03/2009, à 15:26
- flo45
Re : Bash : test d'un caractere
Re bonjour,
Merci pour vos réponses
Je suis confronté a un autre probleme :
Donc j'ai une variable X, qui contient le numéro d'une ligne de mon script (X=4 par exemple) et donc j'aimerais pouvoir extraire tout le contenu de ma ligne X (donc ligne 4), est ce possible ?
Merci encore pour votre aide
#8 Le 03/03/2009, à 16:18
- alexduf
Re : Bash : test d'un caractere
pour alexduf
le 1er exemple sur Comment ca marche ... ne marche pas, même en supprimant les blancs entre les [ [ et les ] ]
ah! toutes mes excuses
Hors ligne
#9 Le 03/03/2009, à 16:41
- cristobal78
Re : Bash : test d'un caractere
pas grave alexduf
tu es tout excusé.;)
Mais si tu es fort en programmation pourrais tu nous expliquer en détail ce que fait (ou plutot ce que devrait faire le "grep" dans l'instruction fournie sur CCM (exemple 1) :
if [ "$(echo $var | grep "^[ [:digit:] ]*$")" ]
ce que je comprends :
Le résultat de echo $var est refilé à grep. Jusque là ça va.
[:digit:] je comprends, c'est dans le man mais avec des [ simples pas des [[ doubles.
^ et $ correspondent à des des chaines vides en début et fin de ligne. C'est quoi ce bazar ?
Par ailleurs je ne suis pas resté bras croisé sur ces 3 test de valeurs numériques. Même si je ne suis pas un cador ils ne me paraissent pas très au point. Il suffit de les tester avec une variable telle que
var=2 z
pour qu'ils plantent.
Finalement moi qui comme certains sur ce fil voudrait disposer d'un test efficace sur le type d'une variable je reste sur ma faim.:(
sos
a+
Laptop Lenovo Ubuntu 20.04 LTS / DELL Mint 20.2 - XFCE / Laptop HP Mint 20.2 - XFCE
Hors ligne
#10 Le 03/03/2009, à 17:25
- flo45
Re : Bash : test d'un caractere
un petit up, j'ai tester avec du grep pas moyen d'y arrivé .. peut etre avec un awk mais jvois pas trop là
#11 Le 03/03/2009, à 19:08
- alexduf
Re : Bash : test d'un caractere
Ben la fonction de Totor fonctionne à merveille :
if [ estNumerique "$Mavar" ]; then
# je fais un truc avec ma var
else
# j'affiche un gros message d'erreur
fi
[edit] : woups, j'avais pas vu il y a une deuxième question. C'est pas une question pour un cours ou un TP des fois ? parce que sinon, je préfère te laisser chercher.
Bon un indice : tail et head [/edit]
Dernière modification par alexduf (Le 03/03/2009, à 19:10)
Hors ligne
#12 Le 03/03/2009, à 19:25
- AnsuzPeorth
Re : Bash : test d'un caractere
J'apporte, avec mes peu de connaissances, ma pierre à l'édifice
if [ "$(echo $var | grep "^[ [:digit:] ]*$")" ]
^ → début de ligne
* → répétition du caractère précédent
$ → fin de ligne
Même si je ne suis pas un cador ils ne me paraissent pas très au point. Il suffit de les tester avec une variable telle que
var=2 z
pour qu'ils plantent.
vous avez eu la réponse par un des maitre en la matiere, donc, le problème vient d'ailleurs !
var=2 z
Une variable avec un espace sans protection...!
fais un echo $var, tu verras le résultat, c'est normal que le z ne soit pas pris en compte.
Donc j'ai une variable X, qui contient le numéro d'une ligne de mon script (X=4 par exemple) et donc j'aimerais pouvoir extraire tout le contenu de ma ligne X (donc ligne 4), est ce possible ?
man grep
EDIT:autant pour moi, je croyais qu'il y avait ce qu'il faut dans grep, mais pas moyen (pas reussi).... utilise sed, regarde dans ma signature.
EDIT2: c'est étonnant,avec [[:digit:]] sans le tild, une var de type "5z", le test fonctionne, avec le tild, il échoue !? Avec [0-9] pas de soucis
Dernière modification par AnsuzPeorth (Le 03/03/2009, à 19:51)
Interface graphique pour bash, python ou autre: glade2script
Support Tchat: http://chat.jabberfr.org/muckl_int/inde … ade2script (Hors ligne)
Hors ligne
#13 Le 03/03/2009, à 21:27
- Totor
Re : Bash : test d'un caractere
Donc j'ai une variable X, qui contient le numéro d'une ligne de mon script (X=4 par exemple) et donc j'aimerais pouvoir extraire tout le contenu de ma ligne X (donc ligne 4), est ce possible ?
il existe effectivement des solutions, tels que (liste non exhaustive) :
avec awk :
awk -v numligne=${X} 'NR==numligne' <fichier>
toujours avec awk :
export X
awk 'NR==ENVIRON["X"]' <fichier>
avec sed :
sed -n "${X}p" <fichier>
et si l'on veut faire dans le tordu :
grep -n ".*" <fichier>|grep "^${X}:"|sed "s/^${X}://"
ou
head -${X} <fichier>|tail -1
etc....
-- Lucid Lynx --
Hors ligne
#14 Le 03/03/2009, à 21:47
- Totor
Re : Bash : test d'un caractere
Ben la fonction de Totor fonctionne à merveille :
if [ estNumerique "$Mavar" ]; then
# je fais un truc avec ma var
else
# j'affiche un gros message d'erreur
fi
ma fonction ne fonctionne que s'il n'y a qu'un seul caractère.
si il y en a plusieurs, il faut effectuer une légère modification (j'y fais d'ailleurs référence lors de ma réponse à quimporte)
:
function estNumerique
{
[[ "$1" =~ ^[[:digit:]]+$ ]]
}
-- Lucid Lynx --
Hors ligne
#15 Le 03/03/2009, à 22:07
- Totor
Re : Bash : test d'un caractere
EDIT2: c'est étonnant,avec [[:digit:]] sans le tild, une var de type "5z", le test fonctionne, avec le tild, il échoue !? Avec [0-9] pas de soucis
Rien d'étonnant :
Avec le tild, la chaine se trouvant à droite du tild est considérée comme une expression régulière étendue. L'expression simple [[:digit:]] (ou [0-9]) indique "contient au moins 1 chiffre". Ce qui est le cas avec 5z.
Sans le tild, l'expression de droite doit vérifier les régles d'expansion de noms bash et doit être respectée en totalité lors de la comparaison. Or, en bash [0-9] signifie "juste un chiffre"
Par ailleurs je ne suis pas resté bras croisé sur ces 3 test de valeurs numériques. Même si je ne suis pas un cador ils ne me paraissent pas très au point. Il suffit de les tester avec une variable telle que
var=2 z
pour qu'ils plantent.Finalement moi qui comme certains sur ce fil voudrait disposer d'un test efficace sur le type d'une variable je reste sur ma faim.sad
la demande portait sur un caractère (et non sur une chaine).
outre le fait de ne pas être un "cador", prends le temps de lire et de comprendre une ligne ne semble pas non plus être ton fort !
-- Lucid Lynx --
Hors ligne
#16 Le 04/03/2009, à 01:22
- cristobal78
Re : Bash : test d'un caractere
Il est pas sympa avec moi monsieur totor.;)
Moi ça fait une semaine que je commence à lire et à essayer de comprendre la ligne de commande. Avant je n'avais jamais vu ça.
J'ai assez vite compris qu'il serait intéressant de savoir dire si une variable est numérique ou non et c'est comme ça (via google) que je suis arrivé dans cette discussion initiée par flo45.
En lisant ce fil où des gens manifestement BEAUCOUP plus forts que moi semblent avoir du mal à se mettre d'accord (il y a pas loin de 15 post), force est de reconnaitre qu'il n'est pas si simple que ça de savoir si une variable est numérique ou non. C'est peut être simple pour certains mais pas pour tous.
Pour le débutant il faut avouer que :
if [ "$(echo $var | grep "^[ [:digit:] ]*$")" ]
n'est pas facile à comprendre.
Merci à AnsuzPeorth pour l'info.:)
J'ai bien lu dans le man que
^ → début de ligne
* → répétition du caractère précédent
$ → fin de ligne
mais je ne comprends pas bien l'utilisation qui en est faite dans la condition if ci-dessus.
Cela veut-il dire "qui commence par un chiffre, qui est suivi de chiffres et qui finit par un chiffre ? C'est ça ?
Enfin pour reprendre la dernière ligne de totor, il est vrai que flo45 a posé une question relative à un caractère mais le lien donné ici par alexduf envoyant sur CCM proposait une méthode portant sur une chaine de caractère, d'où ma tentative malheureuse avec var=2 z
a+
Laptop Lenovo Ubuntu 20.04 LTS / DELL Mint 20.2 - XFCE / Laptop HP Mint 20.2 - XFCE
Hors ligne
#17 Le 04/03/2009, à 10:14
- alexduf
Re : Bash : test d'un caractere
mais je ne comprends pas bien l'utilisation qui en est faite dans la condition if ci-dessus.
Cela veut-il dire "qui commence par un chiffre, qui est suivi de chiffres et qui finit par un chiffre ? C'est ça ?
oui c'est l'idée.
sans le "^" ni le "$", ça aurais voulu dire "qui contient un ou plusieurs chiffres", mais avec pourquoi pas autre chose avant et après.
comme a15b ou a15 ou 15b ou 15
après pour découper un fichier et n'en garder qu'une ligne je trouve le head | tail très pratique., mais, ça c'est les goûts et les couleurs.
En lisant ce fil où des gens manifestement BEAUCOUP plus forts que moi semblent avoir du mal à se mettre d'accord (il y a pas loin de 15 post), force est de reconnaitre qu'il n'est pas si simple que ça de savoir si une variable est numérique ou non. C'est peut être simple pour certains mais pas pour tous.
En fait il existe à peu près autant de manières de faire quelque chose en bash, qu'il existe de programmeurs en bash. D'où les 15 réponses à chaque question, et les désaccords entre les différents membres.
Hors ligne
#18 Le 04/03/2009, à 10:30
- cristobal78
Re : Bash : test d'un caractere
merci alexduf
je vais re-essayer et re-tester cette instruction !
a+
Laptop Lenovo Ubuntu 20.04 LTS / DELL Mint 20.2 - XFCE / Laptop HP Mint 20.2 - XFCE
Hors ligne
#19 Le 04/03/2009, à 12:54
- cristobal78
Re : Bash : test d'un caractere
après plusieurs essais de
echo $var | grep "^[[:digit:]]*$"
j'ai constaté des choses curieuses :
cas var renvoie
------- ------------- ---------------------------------------
1 222 numérique
2 zzzz pas numérique
3 222zzz pas numérique
4 222 zzz 222 donc numérique, qu'est devenu le zzz ?
5 zzz 222 pas numérique
6 222,75 pas numérique
7 222.75 pas numérique
8 222 75 222 donc numérique, le 75 passe à la trappe
Les réponses sont conformes évidement à ce que la commande est censée faire mais cette commande n'est pas totalement "rigoureuse" car elle ne réagit bien que sur les cas 1, 2, 3 et 5.
Sinon :
- le cas 4 n'est clairement pas un nombre !
- au moins l'un des des cas 6 ou 7 devrait exprimer un nombre (selon que le séparateur décimal est un point ou une virgule),
- le cas 8 provoque le même résulta que le cas 4 qui n'a pourtant rien à voir.
Donc dans un script si l'on veut vraiment et sans coup férir s'assurer qu'un chaine est numérique cette commande me parait insuffisante. Qu'en pensent les "bons scripteurs" ?
a+
Dernière modification par cristobal78 (Le 04/03/2009, à 12:55)
Laptop Lenovo Ubuntu 20.04 LTS / DELL Mint 20.2 - XFCE / Laptop HP Mint 20.2 - XFCE
Hors ligne
#20 Le 04/03/2009, à 13:12
- alexduf
Re : Bash : test d'un caractere
4 222 zzz 222 donc numérique, qu'est devenu le zzz ?
8 222 75 222 donc numérique, le 75 passe à la trappe
essaye d'entourer ta variable par des guillemets :
echo "$var" | grep "^[[:digit:]]*$"
6 222,75 pas numérique
7 222.75 pas numérique
echo "$var" | grep "^[[:digit:]]+[,.]?[[:digit:]]*$"
j'ai pas testé mais ça devrais faire l'affaire
Dernière modification par alexduf (Le 04/03/2009, à 13:13)
Hors ligne
#21 Le 04/03/2009, à 13:47
- cristobal78
Re : Bash : test d'un caractere
ça n'a pas l'air de marcher.
J'ai mis les 2 options dans un script nommé testnum2 pour tester plus vite :
#!/bin/sh
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# nom du script = testnum2
# Fonction du script = teste si parametre est numérique ou non
# Syntaxe = ./testnum2 parametre
# Note =
# jcc/04.03.2009
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
var=$1
echo "commande 1"
echo "$var"|grep "^[[:digit:]]*$"
echo "var=$var et \$?=$?"
echo "commande 2"
echo "$var" | grep "^[[:digit:]]+[,.]?[[:digit:]]*$"
echo "var=$var et \$?=$?"
testnum2 123 donne :
testnum2 123
commande 1
123
var=123 et $?=0
commande 2
var=123 et $?=1
donc dans le 1er cas 123 est numérique et pas dans le 2-ème.
C'est pas de la tarte.
a+
Laptop Lenovo Ubuntu 20.04 LTS / DELL Mint 20.2 - XFCE / Laptop HP Mint 20.2 - XFCE
Hors ligne
#22 Le 04/03/2009, à 14:40
- Totor
Re : Bash : test d'un caractere
Si ça peut vous aider ...
function estNumerique { [[ "$1" =~ "^[+-]{0,1}([[:digit:]]+[,.]){0,1}[[:digit:]]+$" ]]; }
$ estNumerique "222 zzz" && echo numerique || echo non numerique
non numerique
$ estNumerique "22,75" && echo numerique || echo non numerique
numerique
$ estNumerique "22 75" && echo numerique || echo non numerique
non numerique
$ estNumerique "+22 75" && echo numerique || echo non numerique
non numerique
$ estNumerique "+22,75" && echo numerique || echo non numerique
numerique
-- Lucid Lynx --
Hors ligne
#23 Le 04/03/2009, à 14:41
- AnsuzPeorth
Re : Bash : test d'un caractere
Vous etes encore à vous battre avec ça ???
var="123 zzz"
echo "$var"|grep "^[[:digit:]]*$"
#n'est pas numérique, donc pas de sortie (ca fonctionne correctement)
maintenant pour tester un nombre a virgule; utilise la comparaison inverse, test si lettre:
[^[:digit:]]
#ou
[[:alpha:]]
var="r12"
echo "$var"| grep "[^[:digit:]]"
#contient au moins un caractère non numérique
r12
Dernière modification par AnsuzPeorth (Le 04/03/2009, à 15:09)
Interface graphique pour bash, python ou autre: glade2script
Support Tchat: http://chat.jabberfr.org/muckl_int/inde … ade2script (Hors ligne)
Hors ligne
#24 Le 04/03/2009, à 14:51
- AnsuzPeorth
Re : Bash : test d'un caractere
Juste un petit mot en passant:
A CAUSE de Totor,
Voilà mon évolution:
echo $var | grep truc #2 commandes un pipe
grep truc <<< $var #1 commande et une redirection
# et maintenant, le ponpon
$var =~ truc #une comparaison
#on peut faire encore plus court ?
J'en apprends des choses ici
EDIT:une petite question qd meme
Pourquoi les " sont necessaire avec l'utilisation d'une ER avec grep pour que ca fonctionne
et inversement avec =~ (si ", marche po ???)
Dernière modification par AnsuzPeorth (Le 04/03/2009, à 15:00)
Interface graphique pour bash, python ou autre: glade2script
Support Tchat: http://chat.jabberfr.org/muckl_int/inde … ade2script (Hors ligne)
Hors ligne
#25 Le 05/03/2009, à 11:21
- Totor
Re : Bash : test d'un caractere
var="123 zzz" echo "$var"|grep "^[[:digit:]]*$" #n'est pas numérique, donc pas de sortie (ca fonctionne correctement)
maintenant pour tester un nombre a virgule; utilise la comparaison inverse, test si lettre:
[^[:digit:]] #ou [[:alpha:]] var="r12" echo "$var"| grep "[^[:digit:]]" #contient au moins un caractère non numérique r12
Ce n'est pas suffisant... que fais-tu des signes + et -, de la virgule, quantité et position ?
C'est pourquoi j'ai fourni une ER complète.
-- Lucid Lynx --
Hors ligne