Home > Back-end >  regex match numbers in an array in a shell script
regex match numbers in an array in a shell script

Time:11-11

I have an array of values coming from bash which i just want to check if there are numbers or not in it. It can contain -, numbers and spaces at the start or end since bash is evaluating this as sting.

Since every number is represented with , at the end i added (,) to the regex.

Basically i want to check if element is a number or not.

The $val look like these.

[ [ -0.13450142741203308, -0.3073260486125946, -0.15199440717697144, -0.06535257399082184, 0.02075939252972603, 0.03708624839782715, 0.04876817390322685 ] ,[ 0.10357733070850372, 0.048686813563108444, -0.1413831114768982, -0.11497996747493744, -0.08910851925611496, -0.04536910727620125, 0.06921301782131195, 0.02547631226480007 ] ]

This is my code which looks at each value and evaluates each. However it doesn't seem to catch the cases.

re='^[[:space:]][ -]?[0-9] ([.][0-9] )?(,)[[:space:]]$'

for j in ${val[*]}
do
  if ! [[ "$j" =~ $re ]] ; then
   echo "Error: Not a number: $j"
  fi
done

Also it needs to ignore cases which throw [ or ] or ],.

Any ideas how to correct this ? Thanks for the help.

CodePudding user response:

It is likely that $val is coming to you as a string.

If you don't need to validate each number as a fully legit number, you can use shell logic to filter those things that are obviously not numbers:

val='[ [ -0.13450142741203308, -0.3073260486125946, -0.15199440717697144, -0.06535257399082184, 0.02075939252972603, 0.03708624839782715, 0.04876817390322685 ] ,[ 0.10357733070850372, 0.048686813563108444, -0.1413831114768982, -0.11497996747493744, -0.08910851925611496, -0.04536910727620125, 0.06921301782131195, 0.02547631226480007 ] ]'

for e in $val; do  # PURPOSELY no quote to break on spaces
    e="${e/,}"
    case $e in
        ''|*[!0-9.\-]*)  printf "'%s' is bad\n" "$e" ;;
        *) printf "'%s' is good\n" "$e" ;;
    esac
done    

Prints:

'[' is bad
'[' is bad
'-0.13450142741203308' is good
'-0.3073260486125946' is good
'-0.15199440717697144' is good
'-0.06535257399082184' is good
'0.02075939252972603' is good
'0.03708624839782715' is good
'0.04876817390322685' is good
']' is bad
'[' is bad
'0.10357733070850372' is good
'0.048686813563108444' is good
'-0.1413831114768982' is good
'-0.11497996747493744' is good
'-0.08910851925611496' is good
'-0.04536910727620125' is good
'0.06921301782131195' is good
'0.02547631226480007' is good
']' is bad
']' is bad

That is super fast but that will fail on malformed 'numbers' such as 123-456


If you do need to filter out malformed numbers, you can use awk for that:

echo "$val" | awk  -v RS="[^0-9. -] " '($0 0==$0)'
# all legit numbers from the string...

CodePudding user response:

If you populate $val with the given string, it's not an array, it's a string. Using it unquoted would apply word splitting to it which splits it into whitespace separated words. The spaces aren't part of the words, and some of the words (the last one in each bracketed sequence) don't end in a comma:

#! /bin/bash
val='[ [ -0.13450142741203308, -0.3073260486125946, -0.15199440717697144, -0.06535257399082184, 0.02075939252972603, 0.03708624839782715, 0.04876817390322685 ] ,[ 0.10357733070850372, 0.048686813563108444, -0.1413831114768982, -0.11497996747493744, -0.08910851925611496, -0.04536910727620125, 0.06921301782131195, 0.02547631226480007 ] ]'

re='^[ -]?[0-9] ([.][0-9] )?,?$'

for j in $val ; do
    if ! [[ $j =~ $re ]] ; then
        echo "Error: Not a number: $j"
    fi
done

To use a bash array, declare it with round parentheses and use whitespace to separate the elements:

#! /bin/bash
val=(-0.13450142741203308 -0.3073260486125946 -0.15199440717697144 -0.06535257399082184 0.02075939252972603 0.03708624839782715 0.04876817390322685 0.10357733070850372 0.048686813563108444 -0.1413831114768982 -0.11497996747493744 -0.08910851925611496 -0.04536910727620125 0.06921301782131195 0.02547631226480007)

re='^[ -]?[0-9] ([.][0-9] )?$'

for j in "${val[@]}" ; do
    if ! [[ $j =~ $re ]] ; then
        echo "Error: Not a number: $j"
    fi
done
  • Related