最も簡単ではありませんが、次のようなことができます:
$ 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
(そのところはは、ksh93で動作するはず${var//pattern/replacement}
オペレータがから来ている)、bash
4.3以降、busyboxのsh
、yash
、mksh
そしてzsh
、もちろんかかわらでzsh
、はるかに単純なアプローチがあります。古いバージョンのではbash
、内部の引用符を削除する必要があります。他のほとんどのシェルで削除された内部引用符でも機能しますが、ksh93では機能しません。
これは$IP
、IPv4アドレスの有効な4進数10進数表現が含まれていることを前提としています(ただし、これは0x6d.0x60.0x4d.0xf
(および一部のシェルでは8進数でも)などの4進数16進数表現でも機能しますが、値は10進数で出力されます)。のコンテンツが$IP
信頼できないソースからのものである場合、それはコマンドインジェクションの脆弱性に相当します。
基本的に、我々はすべてのを交換しているよう.
に$IP
と+256*(
、私たちは評価してしまいます。
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
したがって、IPv4アドレスのように、これらの4バイトから32ビット整数を構築しています(最終的にはバイトが逆になります)。次に>>
、&
ビットごとの演算子を使用して関連するバイトを抽出します。
それ以外の場合、算術パーサーは括弧の不一致について文句を言うため、${param+value}
標準の演算子(ここ$-
では常に設定されることが保証されています)を使用しvalue
ます。ここでシェルは終了見つけることができる))
開口部のために$((
、そしてその後、その内部の拡張は評価する算術式になります行います。
$(((${IP//./"+256*("}))))&255))
代わりに、シェルは、第2および第3の治療でしょう)
終値としてそこ秒))
のため$((
、構文エラーを報告します。
ksh93では、次のことも実行できます。
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash
、mksh
、zsh
は、ksh93のコピーした${var/pattern/replacement}
オペレータをしかし、キャプチャー・グループは、一部を処理していないこと。zsh
異なる構文でサポートします:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bash
は、正規表現一致演算子である形式のキャプチャグループ処理をサポートしていますが、ではサポートしていません${var/pattern/replacement}
。
POSIXly、あなたは使うでしょう:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
のようなnoglob
値の予期せぬ事態を避けるために、サブシェルはこれらの変更の範囲をオプションとに制限します。$IP
10.*.*.*
$IFS
IPv IPv4アドレスは32ビット整数にすぎず、たとえば127.0.0.1は多くの(最も一般的な)テキスト表現の1つにすぎません。ループバックインターフェースの同じ典型的なIPv4アドレスは、0x7f000001または127.1(127.0 1
/ 8クラスAネットワーク上のアドレスであるとここではより適切なものかもしれません)、または0177.0.1、または1の他の組み合わせとして表すこともできます。8進数、10進数、または16進数として表される4つの数値。ping
たとえば、これらすべてを渡すことができ、それらがすべてlocalhostにpingすることがわかります。
or またはor で任意の一時変数(ここでは$n
)を設定することの副作用を気にしない場合は、次のコマンドを使用して、これらすべての表現を32ビット整数に戻すことができます。bash
ksh93
zsh -o octalzeroes
lksh -o posix
$((n=32,(${IP//./"<<(n-=8))+("})))
次に、上記のような>>
/の&
組み合わせですべてのコンポーネントを抽出します。
$ 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
は、算術式に符号付き32ビット整数を使用します。$((# n=32,...))
そこで、符号なし32ビット数を強制的に使用することができます(およびposix
8進定数を認識するためのオプション)。
IFS
のためにread
そこに:IFS=. read -a ArrIP<<<"$IP"