Expressão regular para coincidir com números de ponto flutuante no shell script

1

Estou usando uma expressão regular para corresponder aos números de ponto flutuante:

for f in $float_numbers ; do
    if [ $f =~ "[0-9]*\.?[0-9]*" ] ; then
        echo "****f is $f ****"
    fi
done

onde $float_numbers contém números de ponto flutuante como 1.2 , 10.5 , 4.0 , etc.

Mas nada corresponde.

    
por Gaurav KS 05.12.2016 / 10:56

4 respostas

1

O terdon corrigiu sua sintaxe, mas sua expressão regular está errada:

[0-9]*\.?[0-9]*

Todos os quantificadores ( * , ? ) significam que todas as partes da expressão são opcionais. Isso significa que seu regex corresponderá a todas as strings, incluindo strings vazias e strings que não tenham dígitos.

Para corresponder a um número flutuante, você precisa corresponder a pelo menos um dígito.

([0-9]+\.?[0-9]*)|([0-9]*\.[0-9]+)

Corresponde a alguns dígitos com um ponto decimal opcional e dígitos opcionais (exemplo: 3,14 ou 42), ou alguns dígitos opcionais, mas um ponto decimal obrigatório e dígitos obrigatórios (exemplo: .1234 ou 3.14).

Não está ancorado, por isso a cadeia "PI começa com 3.14 e continua" corresponderá.

Teste:

for n in "" "no digits" 42 3.14 "this is .1234 go"; do 
    if [[ $n =~ ([0-9]+\.?[0-9]*)|([0-9]*\.[0-9]+) ]]; then
        echo "yes -- $n -- ${BASH_REMATCH[0]}"
    fi
done
yes -- 42 -- 42
yes -- 3.14 -- 3.14
yes -- this is .1234 go -- .1234
    
por 05.12.2016 / 12:49
1

Em primeiro lugar, seu código tem um erro de sintaxe e deve reclamar:

bash: [: =~: binary operator expected

Supondo que você esteja executando o bash, mas baseado em seu código, provavelmente você está. Então, no bash, o =~ só funciona dentro de [[ ]] , não [ ] . Você também não deve citar sua expressão regular. Você está procurando por algo assim:

$ for f in $float_numbers; do 
    [[ $f =~ [0-9]*\.?[0-9]* ]] && echo $f
  done
1.2
10.5
4.0

No entanto, como Glenn corretamente apontou , seu regex está errado em primeiro lugar.

    
por 05.12.2016 / 11:28
0

Sugiro que você use este txt2re para criar regex que correspondam ao que você deseja.

Para seu script:

for f in $float_numbers ; do
    if [[ $f =~ ^[+-]?[0-9]+\.?[0-9]*$ ]]; then
        echo "****f is $f ****"
    fi
done

Rexeplanation:

^       # Match start of string
[-+]?   # Match a leading + or - (optional)
[0-9]+  # Match one or more digit
\.?     # Match a literal . (optional, escaped)
[0-9]*  # Match zero or more digits
$       # Match the end of the string

E este é o script perl gerado pelo site anterior que corresponde a números flutuantes

#!/usr/bin/perl

# URL that generated this code:
# http://txt2re.com/index.php3?s=100.3&1

$txt='100.3';

$re1='([+-]?\d*\.\d+)';  # Float 1

$re=$re1;
if ($txt =~ m/$re/is)
{
    $float1=$1;
    print "($float1) \n";
}

#-----
# Paste the code into a new perl file. Then in Unix:
# $ perl x.pl 
#-----
    
por 05.12.2016 / 11:06
0

Uma expressão regular mais precisa para correspondência de floats seria:

^[-+]?([0-9]*\.[0-9]+|[0-9]+\.[0-9]*)$

Isso se resume ao que você consideraria um flutuador. O Python, por exemplo, aceita 5. e .5 como floats válidos e não requer um dígito inicial ou final antes ou depois do . :

>>> 5.
5.0
>>> .5
0.5

Assim, a expressão regex acima trata esses casos e também o caso de borda de apenas . (que não deve ser ).

    
por 05.12.2016 / 12:58