如何从此字符串中提取IP地址和端口号?

时间:2015-06-30 18:40:06

标签: php arrays

我需要使用PHP从textarea元素的输出解析其IP和端口的代理数组。我想知道什么是解决此问题最有效的方法,因为通过textarea上传的列表可能位于proxy:portproxy port(带空格),在这两种情况下每个代理都会被换行符分开。

例如,如果在两个不同的场合上传了以下列表:

34.345.32.1 9032
4.3.21.234 2023
45.31.45.324 1025

34.345.32.1:9032
4.3.21.234:2023
45.31.45.324:1025

然后在两种情况下得到的数组都是

$proxies = array (
  array('34.345.32.1',9032),
  array('4.3.21.234',2023),
  array('45.31.45.324',1025)
);

我已经尝试了以下代码,但是在var_dump() array上没有打印任何内容。

$array = explode("\n", $_POST['proxies']);
$array2 = explode(" " $array);

3 个答案:

答案 0 :(得分:1)

您可以使用简单的foreach循环遍历数组,strpos来检测分隔符

$proxies = explode("\n", $_POST['proxies']);
foreach($proxies as $key => $value){
    if(strpos($value, ' ')){
        $proxies[$key] = explode(' ', $value);  
    } else {
        $proxies[$key] = explode(':', $value);  
    }
}

print_r($proxies); 

这是一个基本示例,您需要对此进行扩展,以确保您的数据在此之后进行标准化。

答案 1 :(得分:0)

为了验证代理,我在我的生产站点上使用此功能。

    /**
     * Validate IP and PORT | This will give you array of proxy into IP and PORT
     * Valid IP Address (0.0.0.0 - 255.255.255.255): Valid port (1-65535)
     *  IP = $matches[1]
     *  PORT = $matches[2]
     * @return boolean|array
     */
    public function proxyIpPort($proxy)
    {
        try {
            //Valid IP Address (0.0.0.0 - 255.255.255.255): Valid port (1-65535)
            if (preg_match('~\b([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):([0-9]{1,10}\b)~', $proxy, $matches)) {

                //if port range doesnot match return error
                if (!preg_match('/^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/m', $matches[2], $arraystr)) {
                    return array(
                        'success' => false,
                        'error' => 'Invalid Port Range',
                        'ip' => $matches[1],
                        'port' => $matches[2],
                    );
                }

                if (filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
                    return array(
                        'success' => false,
                        'error' => 'Invalid IP Address',
                        'ip' => $matches[1],
                        'port' => $matches[2],
                    );
                }

                if (filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false) {
                    return array(
                        'success' => false,
                        'error' => 'Private IP provided',
                        'ip' => $matches[1],
                        'port' => $matches[2],
                    );
                }

                if (filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) === false) {
                    return array(
                        'success' => false,
                        'error' => 'Reserve IP provided',
                        'ip' => $matches[1],
                        'port' => $matches[2],
                    );
                }

                //all verifications done
                return array(
                    'success' => true,
                    'ip' => $matches[1],
                    'port' => $matches[2],
                );
            }

            //all validations failed return invalid ip
            return array(
                'success' => false,
                'error' => 'Invalid IP:PORT'
            );
        } catch (\Throwable $th) {
            return array(
                'success' => false,
                'error' => $th,
            );
        }
    }

此功能将为您提供对公共代理的精确验证。

关于没有使用 : 的代理

$txt = "34.345.32.1 9032
4.3.21.234 2023
45.31.45.324 1025";

$proxies = str_replace(" ", ":", $txt); //replace the empty space between ip and port with `:`
$proxies = str_replace("\n", ",", $proxies); // replace the new line `\n` with `,` to convert text into array
$proxies_array = explode(",", $proxies);
print_r($proxies_array);

使用给定的代理数组并使用 foreach 一一测试每个代理?

答案 2 :(得分:0)

此任务接收用户提供的输入(textarea),然后尝试解析具有轻微可变性的字符串。这是正则表达式函数的一个很好的候选。

以简洁的模式提供确切所需输出的一种方法是:(Demo)

preg_match_all('~(\d{1,3}(?:\.\d{1,3}){3})[: ]\K\d{4}~', $string, $matches, PREG_SET_ORDER);

var_export(array_map('array_reverse', $matches));

上面是捕获代理子串,然后匹配不同的分隔符,然后忘记那些匹配的字符,然后匹配端口子串作为“全串匹配”。这样做时,$matches 数组具有相反顺序的子数组元素——如果顺序很重要,您可以在每个子数组上调用 array_reverse()

否则,您可以不那么花哨,只捕获代理和端口子字符串并容忍不需要的全字符串匹配。 (Demo)

preg_match_all('~(\d{1,3}(?:\.\d{1,3}){3})[: ](\d{4})~', $string, $matches, PREG_SET_ORDER);

var_export($matches);  // just access the [1] and [2] subarray values

我发现 double-explode() 技术对这项任务的吸引力不大,因为正如我之前所说,这是用户提供的数据,不能信任。

如果我要使用非正则表达式解决方案(不提供验证),我会使用 D.R.Y.:

$proxies = [];
foreach (explode("\n", $_POST['proxies']) as $line) {
    $proxies[] = explode(
        strpos($value, ':') ? ':' : ' ',
        $value
    );
}