# BASH Les pièges du mode numérique

**URL:** <https://www.debian-fr.org/t/bash-les-pieges-du-mode-numerique/68403>\
**Category:** Programmation\
**Created:** [Février 29, 2016, 3:47 UTC](https://www.debian-fr.org/t/bash-les-pieges-du-mode-numerique/68403 "2016-02-29T15:47:18Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![littlejohn75](https://www.debian-fr.org/user_avatar/www.debian-fr.org/littlejohn75/32/3840_2.png) [@littlejohn75](https://www.debian-fr.org/u/littlejohn75)\
**Post date:** [Février 29, 2016, 3:47 UTC](https://www.debian-fr.org/t/bash-les-pieges-du-mode-numerique/68403/1 "2016-02-29T15:47:18Z")

</div>

L’interpréteur _bash_ embarque un mode arithmétique très pratique pour des calculs sur des entiers.

Par exemple pour tester si une chaîne est de la forme aaa.bbb.ccc.ddd où les aaa, … ddd sont des entiers entre 0 et 255 (adresse IPv4) on peut être tenter d’extraire ce qui est séparé par des ‘.’ et de tester que l’on ne dépasse pas 255.

`  
#!/bin/bash

set -euo pipefail  
# shopt -o -s nounset

# validation function one parameter “$IP” required  
function isIPv4()  
{  
(( $# == 1 )) || return 1  
declare v="" # v without numeric/integer attribute  
declare -a values  
IFS=’.’ read -a values \<\<\< "$1"  
declare -i nvals=${#values[@]}  
(( nvals == 4 )) || return 1  
declare -i vn=9

# declare -p values v vn &\>\>$FLOG

```
for v in "${values[@]}"
do
  # declare vn="$v" || return 1 # si -i et v="ttt" unbound variable (avec set -u)
  set +u
    vn="${v:-}"
  set -u
    (( vn >= 0 )) || return 1
    (( vn <= 255 )) || return 1
    # a value of "xxx" gives 0 in numeric context automatically
    if (( vn == 0 )); then
       # [["$v"]] || return 1
       [["W${v}" == "W0"]] || return 1
    fi
done
return 0

```

}

# validation function one parameter “$IP” required  
isIP()  
{  
(( $# == 1 )) || return 1  
declare v="" # v without numeric/integer attribute  
declare -a values # =( “placeholder” )

```
IFS='.' read -a values <<< "$1"

```

# set – “${values[@]:+}” break $good

```
set -- "${values[@]:-}"
(( $# == 4 )) || return 1

for v
do
  set +u
    declare -i vn="${v}"
  set -u
    (( vn >= 0 )) || return 1
    (( vn <= 255 )) || return 1
    # a value of "xxx" gives 0 in numeric context automatically
    if (( vn == 0 )); then
       # [["$v"]] || return 1
       [["W${v}" == "W0"]] || return 1
    fi
done
return 0

```

}

# run the given preducate :  
function vraifaux() {  
"$@" && echo ‘vrai’ || echo “faux”  
}

test\_IPs() {  
declare IP res res2  
printf " IP\t\t\tresult\tres2\n"  
for IP  
do  
res=$(vraifaux isIPv4 “$IP”)  
res2=$(vraifaux isIP “$IP”)  
printf “”%s"\t\t%s\t%s\n" “$IP” “$res” "$res2"  
done  
}

do\_tests() {  
declare vide="" space=" " good="10.67.24.198"  
test\_IPs “$good” “10.67.24.0” "10.67.24"  
echo

# set -x  
QQQ="sss"  
test\_IPs “$good” “$vide” “$space” “10.67.24.QQQ”  
}

(( $# == 0 )) && do\_tests || test\_IPs “$@”

## `

Le nouveau widget d’édition est une vraie catastrophe 😡

Lançcons notre test intégré  
`  
fp2x@drhpcmsa:/tmp$ ./test\_IP.sh  
IP result res2  
"10.67.24.198" vrai vrai  
"10.67.24.0" vrai vrai  
"10.67.24" faux faux

## IP result res2 "10.67.24.198" vrai vrai "" faux faux " " faux faux "10.67.24.QQQ" faux faux `

On pourrait se dire que c’est gagné! Un lecteur attentif aura remarqué les bidouilles set +u/set -u  
En fait nous n’avons que repoussé le problème.  
`fp2x@drhpcmsa:/tmp$ AA="BB" BB="CC" CC="DD" DD="10" ./test_IP.sh 10.10.10.10 AA. BB.CC.DD IP result res2 "10.10.10.10" vrai vrai "AA.BB.CC.DD" vrai vrai`

La chaîne “AA.BB.CC.DD” est évaluée comme “10.10.10.10” et passe le test!

D’ailleurs ces fonctions sont loin d’être robustes  
`fp2x@drhpcmsa:/tmp$ AA="BB" BB="CC" CC="DD" DD="AA" ./test_IP.sh 10.10.10.10 AA.BB.CC.DD IP result res2 "10.10.10.10" vrai vrai ./test_IP.sh: ligne 21: DD : dépassement du niveau de récursivité dans l'expression (le symbole erroné est "DD")`

On peut rendre isIP plus robuste mais cela demande d’utiliser d’autres techniques comme par exemple les expressions rationnelles et cela est laissé comme exercice au lecteur 😄

## Cordialement, Regards, Mit freundlichen Grüßen, مع تحياتي الخالصة

F. Petitjean  
Bureau Veritas

---

<div class="post-metadata">

**Author:** ![littlejohn75](https://www.debian-fr.org/user_avatar/www.debian-fr.org/littlejohn75/32/3840_2.png) [@littlejohn75](https://www.debian-fr.org/u/littlejohn75)\
**Post date:** [Février 29, 2016, 4:04 UTC](https://www.debian-fr.org/t/bash-les-pieges-du-mode-numerique/68403/2 "2016-02-29T16:04:29Z")

</div>

Je viens de trouver dans un autre message ma manière d’avoir le verbatim sur plusieurs lignes ce serait avec 3 backtics

````auto
#!/bin/bash

set -euo pipefail
# shopt -o -s nounset

# validation function one parameter "$IP" required
isIP()
{
    (( $# == 1 )) || return 1
    declare v="" # v without numeric/integer attribute
    declare -a values # =( "placeholder" )

    IFS='.' read -a values <<< "$1"
 # set -- "${values[@]:+}" break $good
    set -- "${values[@]:-}"
    (( $# == 4 )) || return 1

   for v
    do
      set +u
        declare -i vn="${v}"
      set -u
        (( vn >= 0 )) || return 1
        (( vn <= 255 )) || return 1
        # a value of "xxx" gives 0 in numeric context automatically
        if (( vn == 0 )); then
           # [["$v"]] || return 1
           [["W${v}" == "W0"]] || return 1
        fi
    done
    return 0
}
```
Et c'est en couleur ! Que demande le peuple?

Cordialement,
Regards,
Mit freundlichen Grüßen,
مع تحياتي الخالصة  
---
F. Petitjean
```
# ;email.b98;"naej"v
      >,v
      |:<"F. Petit"<
 v ,a<
 >aab*1-:2+:c-:7-2/:88*5++:9-9-:a9++:b-:9+:d-:7a++:1-: aa+-:4+:d+:3+:a9+-88v
 @_,#! #:<+2*aa+8+9:-d:+b:-c:+6:-a:-6*bb-+2*88:+b:-f:+b:-b:+a:+5:+4:-d:*ab*<

```
````
