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), bash
4.3+, Busybox sh
, yash
, mksh
und zsh
, obwohl natürlich in zsh
, gibt es viel einfachere Ansätze . In älteren Versionen von bash
mü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 $IP
eine 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 $IP
aus 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 $IP
mit +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, value
weil 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. zsh
unterstützt es mit einer anderen Syntax:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bash
unterstü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 noglob
vermeiden böse Überraschungen für Werte $IP
wie 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 1
Adresse 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 ping
Beispiel 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 bash
oder ksh93
oder zsh -o octalzeroes
oder 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
mksh
verwendet 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 posix
Option, Oktalkonstanten zu erkennen).
IFS
für dieread
dortIFS=. read -a ArrIP<<<"$IP"