bash ponto de expressão regular "." character not matching

0

A string que estou tentando corresponder é um endereço IP e eu vi alguns exemplos na web. No entanto, parece que estou perdendo algo que pode ou não ter a ver com as diferenças entre as convenções de expressão regular. (pcre, ere, ??)

Para dividi-lo ao ponto que estou perdendo, aqui está o endereço IP parcial que estou tentando corresponder:

ip="255.255."

Esta é uma expressão regular que tenta corresponder acima de ip:

^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){2}

É bash, então eu tenho isso para comparar:

[[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){2} ]] && echo "ok"

Infelizmente, isso não corresponde.

Tanto quanto eu sei, estou autorizado a escapar do. porque eu quero combinar com um caractere de ponto, não apenas qualquer caractere. (o que. significa no regexp para o melhor do meu conhecimento).

Isto é o que acontece quando eu removo a fuga antes do ponto para ilustrar a declaração acima:

# ip="255.255."
# [[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?.){2} ]] && echo "ok"
ok
# ip="255X255Y"
# [[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9] [0-9]?.){2} ]] && echo "ok"
ok

Isso não é correto para corresponder ip (parcial) neste caso.

Por que isso não corresponde a isso:

# ip="255.255."
# [[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){2} ]] && echo "ok" || echo "nope"
nope

Existem dois grupos e cada um deles é "255". e essa parte combina muito bem assim:

# ip="255."
# [[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.) ]] && echo "ok" || echo "nope"
ok  

EDITAR : algumas informações adicionais que possivelmente resolvem meu problema:

só notei o seguinte:

# ip="172.15.11.10"
# [[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){2} ]] && echo "ok" || echo "nope"
ok
# ip="172.15."
# [[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){2} ]] && echo "ok" || echo "nope"
ok

E quando o seguinte agrupamento é feito:

# [[ ${ip} =~ ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){2} ]] && echo "ok" || echo "nope"
nope
# [[ ${ip} =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){2} ]] && echo "ok" || echo "nope"
ok

Portanto, agrupar a parte "número" na frente do "ponto" do separador resolve o problema?

# ip="255.255."
# [[ ${ip} =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){2} ]] && echo "ok" || echo "nope"
ok

Estou inclinado a pensar que isso resolve, no entanto, eu ainda não entendo o porquê.

EDIT : o regexp completo para o endereço IP é este aqui:

^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

Este é o mesmo mencionado por Jeff na resposta abaixo.

    
por lievendp 21.11.2018 / 15:26

1 resposta

3

Os parênteses estavam no lugar errado.

Na regex com falha, você agrupou as possibilidades do octeto com as alternâncias:

^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.)

... que corresponderia ao início da linha ^ seguido por:

  • 25[0-5] ou
  • 2[0-4][0-9] ou
  • [01]?[0-9][0-9]?\.

Observe como o período faz parte da 3ª alternação possível. Isso força a regex a corresponder ao 255 inicial, deixando o período seguinte inigualável.

Você quer que o octeto e o período sejam repetidos, então agrupe o regex assim:

^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){2}

ou assim:

^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$

... para que haja quatro octetos.

Isso força o endereço IP a aparecer sozinho em uma linha. Se você não se importa onde na linha o endereço IP é exibido, elimine as âncoras inicial ( ^ ) e final ( $ ).

No Linux, para uma ajuda visual no teste, você pode usar grep --color=always -E ... , por exemplo:

$ ip=jeff-255.255.255.255-foo
$ echo "$ip" | grep --color=always -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
jeff-255.255.255.255-foo

... onde o 255.255.255.255 aparece em cores.

    
por 21.11.2018 / 15:45