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), bash4.3+, busybox sh, yash, mkshe 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 $IPcontenha 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 $IPvier de uma fonte não confiável, isso equivaleria a uma vulnerabilidade de injeção de comando.
Basicamente, como estamos substituindo cada .no $IPcom +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 valueporque, 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. zshsuporta com uma sintaxe diferente:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bashsuporta 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 noglobevitar surpresas ruins para valores de $IPlike 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 1endereç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, pingpor 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 bashou ksh93ou zsh -o octalzeroesou 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
mkshusa 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 posixopção para reconhecer constantes octais).
IFSparareadlá:IFS=. read -a ArrIP<<<"$IP"