Nicht die einfachste , aber Sie könnten so etwas tun:
$ 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
Das sollte in ksh93 arbeiten (wo die ${var//pattern/replacement}Betreiber herkommt), bash4.3+, Busybox sh, yash, mkshund zsh, obwohl natürlich in zsh, gibt es viel einfachere Ansätze . In älteren Versionen von bashmüssten Sie die inneren Anführungszeichen entfernen. Es funktioniert mit den inneren Anführungszeichen, die auch in den meisten anderen Shells entfernt wurden, jedoch nicht mit ksh93.
Dies setzt voraus, dass $IPeine gültige Quad-Dezimal-Darstellung einer IPv4-Adresse enthalten ist (obwohl dies auch für Quad-Hexadezimal-Darstellungen wie 0x6d.0x60.0x4d.0xf(und in einigen Shells sogar oktal) funktionieren würde, die Werte jedoch dezimal ausgeben würde). Wenn der Inhalt von $IPaus einer nicht vertrauenswürdigen Quelle stammt, würde dies eine Sicherheitsanfälligkeit bezüglich Befehlsinjektion darstellen.
Im Grunde genommen , wie wir alle sind zu ersetzen .in $IPmit +256*(, wir Auswertung am Ende:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
Also haben wir ein 32 - Bit - Integer aus diesem 4 Bytes wie eine IPv4 - Adresse sind die Konstruktion ist schließlich (wenn auch mit den Bytes umgekehrt) ¹ und dann mit den >>, &Bitoperatoren das relevante Bytes zu extrahieren.
Wir verwenden den ${param+value}Standardoperator (hier $-wird immer festgelegt), anstatt nur, valueweil sich der arithmetische Parser sonst über nicht übereinstimmende Klammern beschweren würde. Die Shell hier kann den Abschluss ))für die Öffnung $((finden und dann die Erweiterungen im Inneren ausführen, die dazu führen, dass der arithmetische Ausdruck ausgewertet wird.
Mit $(((${IP//./"+256*("}))))&255))stattdessen behandeln würde die Schale der zweiten und dritten )s dort als Schließ ))für $((und einen Syntaxfehler melden.
In ksh93 können Sie auch Folgendes tun:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash, mksh, zsh Haben ksh93 des kopierten ${var/pattern/replacement}Betreiber aber nicht , dass der Fang-Gruppe einen Teil der Handhabung. zshunterstützt es mit einer anderen Syntax:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bashunterstützt eine Form der Erfassung von Erfassungsgruppen in seinem Regexp-Matching-Operator , jedoch nicht in ${var/pattern/replacement}.
POSIXly würden Sie verwenden:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
Die noglobvermeiden böse Überraschungen für Werte $IPwie 10.*.*.*die Subshell den Umfang dieser Änderungen an Optionen zu begrenzen und $IFS.
¹ Eine IPv4-Adresse ist nur eine 32-Bit-Ganzzahl und 127.0.0.1 ist beispielsweise nur eine von vielen (wenn auch am häufigsten verwendeten) Textdarstellungen. Dieselbe typische IPv4-Adresse der Loopback-Schnittstelle kann auch als 0x7f000001 oder 127.1 (hier möglicherweise besser geeignet, um zu sagen, dass es sich um die 1Adresse im 127.0 / 8-Klasse-A-Netzwerk handelt) oder 0177.0.1 oder die anderen Kombinationen von 1 dargestellt werden bis 4 Zahlen ausgedrückt als Oktal, Dezimal oder Hexadezimal. Sie können all diese zum pingBeispiel an übergeben und Sie werden sehen, dass sie alle localhost pingen.
Wenn Ihnen der Nebeneffekt des Festlegens einer beliebigen temporären Variablen (hier $n) in bashoder ksh93oder zsh -o octalzeroesoder nichts ausmacht lksh -o posix, können Sie einfach alle diese Darstellungen zurück in eine 32-Bit-Ganzzahl konvertieren mit:
$((n=32,(${IP//./"<<(n-=8))+("})))
Und dann extrahieren Sie alle Komponenten mit >>/ &Kombinationen wie oben.
$ 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
mkshverwendet vorzeichenbehaftete 32-Bit-Ganzzahlen für seine arithmetischen Ausdrücke. Dort können Sie $((# n=32,...))die Verwendung vorzeichenloser 32-Bit-Zahlen erzwingen (und die posixOption, Oktalkonstanten zu erkennen).
IFSfür diereaddortIFS=. read -a ArrIP<<<"$IP"