Não é o mais fácil , mas você pode fazer algo como:
$ IP=109.96.77.15
$ echo "$((${-+"(${IP//./"+256*("}))))"}&255))"
109
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>8&255))"
96
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>16&255))"
77
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>24&255))"
15
Isso deve funcionar no ksh93 (onde esse ${var//pattern/replacement}
operador vem), bash
4.3+, busybox sh
, yash
, mksh
e zsh
, embora, naturalmente , em zsh
, existem abordagens muito mais simples . Nas versões anteriores bash
, você precisaria remover as aspas internas. Também funciona com as aspas internas removidas na maioria dos outros shells, mas não no ksh93.
Isso pressupõe que $IP
contenha uma representação quad-decimal válida de um endereço IPv4 (embora isso também funcione para representações quad-hexadecimais como 0x6d.0x60.0x4d.0xf
(e até octal em alguns shells), mas produziria os valores em decimal). Se o conteúdo $IP
vier de uma fonte não confiável, isso equivaleria a uma vulnerabilidade de injeção de comando.
Basicamente, como estamos substituindo cada .
no $IP
com +256*(
, acabamos avaliação:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
Então, nós estamos construindo um inteiro de 32 bit fora dessas 4 bytes como um endereço IPv4 em última análise, é (embora com os bytes invertida) ¹ e, em seguida, usando os >>
, &
operadores bit a bit para extrair os bytes relevantes.
Usamos o ${param+value}
operador padrão (aqui no $-
qual é garantido que seja sempre definido) em vez de apenas value
porque, caso contrário, o analisador aritmético reclamaria de parênteses incompatíveis. O shell aqui pode encontrar o fechamento ))
para a abertura $((
e , em seguida, executar as expansões dentro que irá resultar na expressão aritmética para avaliar.
Com $(((${IP//./"+256*("}))))&255))
vez, o shell trataria o segundo e terceiro )
s lá como o fechamento ))
de $((
e relatar um erro de sintaxe.
No ksh93, você também pode:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash
, mksh
, zsh
Copiou de ksh93 ${var/pattern/replacement}
operador, mas não que a captura do grupo manipulação parte. zsh
suporta com uma sintaxe diferente:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bash
suporta alguma forma de manipulação de grupo de captura em seu operador de correspondência regexp , mas não em ${var/pattern/replacement}
.
POSIXly, você usaria:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
Para noglob
evitar surpresas ruins para valores de $IP
like 10.*.*.*
, o subshell para limitar o escopo dessas alterações às opções e $IFS
.
Address Um endereço IPv4 é apenas um número inteiro de 32 bits e 127.0.0.1, por exemplo, é apenas uma das muitas (embora as mais comuns) representações textuais. O mesmo endereço IPv4 típico da interface de loopback também pode ser representado como 0x7f000001 ou 127.1 (talvez um mais apropriado aqui para dizer que é o 1
endereço na rede classe 127.0 / 8 classe A), ou 0177.0.1 ou as outras combinações de 1 a 4 números expressos em octal, decimal ou hexadecimal. Você pode passar todos para, ping
por exemplo, e verá que todos executarão ping no host local.
Se você não se importa com o efeito colateral de definir uma variável temporária arbitrária (aqui $n
), em bash
ou ksh93
ou zsh -o octalzeroes
ou lksh -o posix
, você pode simplesmente converter todas essas representações em um número inteiro de 32 bits com:
$((n=32,(${IP//./"<<(n-=8))+("})))
E então extraia todos os componentes com >>
/ &
combinações como acima.
$ IP=0x7f000001
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ IP=127.1
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ echo "$((n=32,((${IP//./"<<(n-=8))+("}))>>24&255))"
127
$ perl -MSocket -le 'print unpack("L>", inet_aton("127.0.0.1"))'
2130706433
mksh
usa números inteiros de 32 bits assinados para suas expressões aritméticas, você pode usá $((# n=32,...))
-lo para forçar o uso de números de 32 bits não assinados (e a posix
opção para reconhecer constantes octais).
IFS
pararead
lá:IFS=. read -a ArrIP<<<"$IP"