PHP读取防火墙拒绝列表仅返回单个数组元素问题排查
问题:读取防火墙拒绝列表到PHP数组仅返回单个元素
我尝试将服务器防火墙拒绝列表读取到PHP数组中,但仅返回一个数组元素。以下是列表的部分内容:
46.229.168.0/24 # {do not delete} - Thu Nov 14 01:23:31 2019 43.128.88.156 # lfd: Tue Dec 12 11:11:01 2023 150.158.44.71 # lfd: t 3600 secs - Tue Dec 12 11:18:27 2023
我尝试了两种读取文件到数组的方法:
$ips = file('log.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); print_r($ips); $file = fopen('log.txt',"r"); $ips = []; while ($line = fgets($file)) { $ips[] = $line; } fclose($file); print_r($ips);
两种方法的返回结果均为:
Array ( [0] => 46.229.168.0/24 # {do not delete} - Thu Nov 14 01:23:31 2019 43.128.88.156 # lfd: (sshd) Failed SSH login from 43.128.88.156 (SG/Singapore/-): 5 in the last 3600 secs - Tue Dec 12 11:11:01 2023 150.158.44.71 # lfd: (sshd) Failed SSH login from 150.158.44.71 (CN/China/-): 5 in the last 3600 secs - Tue Dec 12 11:18:27 2023 )
我多次使用过file()函数,因此推测问题出在输入文件的格式上,该文件是服务器防火墙列表的直接副本。请问我操作有误吗?是否需要使用其他代码?
解决方案
问题确实出在文件的换行符格式上。服务器生成的防火墙列表可能使用了**仅回车符(\r)**作为换行标记,而PHP的file()和fgets()默认只识别换行符(\n)或者回车换行符组合(\r\n),因此会把整个文件当成一行读取。
可以通过以下几种方式解决:
替换换行符后再分割
先读取整个文件内容,将所有的\r替换成\n,再按行分割:$content = file_get_contents('log.txt'); // 替换所有回车符为换行符,同时处理可能的混合换行情况 $content = str_replace(["\r\n", "\r"], "\n", $content); $ips = preg_split('/\n+/', trim($content)); print_r($ips);使用自定义的行读取逻辑
打开文件后,按字符读取并识别\r作为换行标记:$file = fopen('log.txt', 'r'); $ips = []; $currentLine = ''; while (($char = fgetc($file)) !== false) { if ($char === "\r") { // 遇到回车符,视为一行结束 if (!empty(trim($currentLine))) { $ips[] = trim($currentLine); } $currentLine = ''; } elseif ($char !== "\n") { // 排除多余的换行符,避免空行 $currentLine .= $char; } } // 处理最后一行 if (!empty(trim($currentLine))) { $ips[] = trim($currentLine); } fclose($file); print_r($ips);修改文件的换行符格式
如果有权限修改文件,可以使用服务器上的命令转换换行符,比如在Linux系统下使用sed命令替换:sed -i 's/\r/\n/g' log.txt
内容的提问来源于stack exchange,提问作者user3052443
相关产品推荐
相关产品推荐

