如何在 PHP 中将此字符串转换为人类可读的 IP 地址?



>我有一个表示IPv4地址的字符串:

$ip = 'x7Fx01';

当我试图把它传递给inet_ntop($ip)时,它给了我悲伤:

PHP 警告:inet_ntop((:无效in_addr值

如果我使用双引号手动声明变量,它可以工作:

$ip = "x7Fx01";
inet_ntop($ip); // "127.0.0.1"

但是,我不会手动声明这些变量。我正在使用对象中提供给我的东西。

如何将'x7Fx01'转换为inet_ntop()接受的字符串?

换句话说,我怎样才能让 PHP 从字面上解析一个字符串,就好像我用双引号手动声明它一样?


一些有趣的事实:

gettype('x7Fx01'); // string
gettype("x7Fx01"); // string
ord('x7Fx01'); // 92
ord("x7Fx01"); // 127
implode(unpack('H*', 'x7Fx01')); // 5c7837465c305c305c783031
implode(unpack('H*', "x7Fx01")); // 7f000001
mb_detect_encoding('x7Fx01'); // ASCII
mb_detect_encoding("x7Fx01"); // UTF-8
"x7Fx01" == 'x7Fx01'; // false
// and for the haters
long2ip('x7Fx01'); // PHP Warning:  long2ip() expects parameter 1 to be integer, string given

一种可能性是将字符串解析为其组件部分(从开始(; 将它们转换为十进制等效值并使用chr来获取原始字符。然后可以将这些连接到适合inet_ntop的字符串中:

$ip = 'x7Fx01';
preg_match_all('/\x?([dA-F]+)/', $ip, $parts);
$ip = implode('', array_map(function ($v) { return chr(hexdec($v)); }, $parts[1]));
echo inet_ntop($ip);

另一种选择是使用pack,在剥离x部分并用00替换后:

$ip = 'x7Fx01';
$ip = pack('H*', str_replace(array('x', ''), array('', '00'), $ip));
echo inet_ntop($ip);

在这两种情况下,输出都是:

127.0.0.1

3v4l.org 演示

问题是你得到了二进制字符串的文字ASCII输出,而不是你期望的实际二进制值。我不确定您是如何获得文字 ASCII 值的。有一种方法可以转换它,但你不会喜欢它。

您可以使用eval()来完成您要做的事情。所有关于eval()是邪恶的论据仍然适用。

$ip = 'x7Fx01';
eval("$ip = "$ip";");
echo inet_ntop($ip);

这将打印出127.0.0.1.

由于二进制并不总是产生文字 ASCII 字符,我担心您会在字符串中看到文字字符,并且这些字符不会正确转换为您期望的二进制值。

例如,以下是打印到 Psysh 中屏幕的字符:

>>> hex2bin('7f000001') // This is 127.0.0.1
=> "x7Fx01"
>>> hex2bin('ffffffff') // This is 255.255.255.255
=> b"ÿÿÿÿ"

第一个值看起来很熟悉,对吧?这是我们可以使用eval()转换回二进制字符串的字符串文字,就像我们在上面的例子中所做的那样。但是ffffffff的二进制值是另一回事。如果我们尝试转换它,它不会给我们预期的255.255.255.255值。

$ip = 'ÿÿÿÿ';
eval("$ip = "$ip";");
echo inet_ntop($ip);

在这种情况下,inet_ntop()返回false,但我们知道它应该有效:

>>> inet_ntop(hex2bin('ffffffff'));
=> "255.255.255.255"

因此,我担心任何将这些值从字符串文字转换为二进制字符串的尝试都不会在所有情况下都有效,无论是使用eval()还是此处提供的任何其他答案。

但是,如果一切都以格式出现,其中每个"段"都是x00格式中的零或十六进制值,那么您应该处于良好状态,因为它们是相同的:

>>> "xFFxFFxFFxFF"
=> b"ÿÿÿÿ"

你可以像这样制作自己的函数

function convertStringToInAddr(string $string) {
$return = null;
$exploded = explode("\", $string);
foreach($exploded as $hex) {
if( $hex != "" ) {
$return .= chr(hexdec(str_replace("x", "", $hex)));
}
}
return $return;
}

最新更新