从修剪区域文件(txt文件)收集名称服务器阵列的Php脚本


Php script to Collect An Array of Nameservers From a Trimmed Zone File (txt file)

我有两个正在使用的文本文件。第一个文本文件名为get-domain.txt,它包含以下格式的域列表:

000,
1,
10,
101domain,
11,

第二个文件是一个名为final-file.txt的修剪区域文件,它包含以下格式的域及其名称服务器:

000 NS ns2.mailart.com. 
 NS ns3.mailart.com. 

1 NS NS1.MAILART.COM. 
 NS NS2.MAILART.COM. 

10 NS pns22.cloudns.net.
 NS ns24.cloudns.net. 

101domain NS ns1.101domain.com. 
 NS ns2.101domain.com. 

11 NS f1g1ns1.dnspod.net.
 NS f1g1ns2.dnspod.net. 

我已经编写了一个脚本来遍历这两个文件,当第一个文件中的域与第二个文件中匹配时,我应该收集该域的名称服务器,并将它们以以下格式写入另一个名为file-to-compare.txt的文件:

000.mw, ns2.mailart.com.,
000.mw, ns3.mailart.com.,

然而,我面临的问题是,我编写的php脚本只能收集第一个名称服务器。如果一个域的名称服务器不止一个,则无法获取其余名称服务器。以下是我的脚本输出示例:

000.mw, ns2.mailart.com., 
000.mw, ns2.mailart.com.,  

以下是我的代码:

//open a file to read domains from
$domains = fopen("get-domain-final.txt", "r") or die("Cant open the get-      domain-final file"); //open the file containing all domains
while (!feof($domains))
{
    $dom_arr = array(); $d = 0; //define n declare domain array n its index
    $m=0; //checks if an array contains a value
    $b=0; 
    $array = explode(",", fgets($domains)); //make an array using comma inorder to get the domain
    $domain=$array[0];
    //***************** opening final trimed zone file**********************//
    $exp = "final-file.txt"; 
    $fp = fopen("$exp",'r') or die("Cant open the final trimed zone file"); 
    //***************** opening file to write our results to**********************//
    $regfile = "file-to-compare.txt";  //assign the file to a variable
    $fh = fopen($regfile,'a') or die("Cant open the reg file"); 
    while(!feof($fp)){
         $blank=fgets($fp); //get the line from the file  //it wrkd as well--> $blank=trim(fgets($fp));if(empty($blank))
         $fields = explode(" ",$blank);  //explode the line by space
         //echo $fields[2]."<br/>"; // display de exploded values of array i.e verizon.mw 
         //check for the NS of the same domain as above
         if( ("$domain") == strtolower((trim($fields[0]))) ){ //get NSs of the domain
            //if ("$domain" == "$fields[0]")$b=1;} //ctrl the lines of that domain to read its NS
            //if ($b>=1){break;}
            //echo $fields[2]."<br/>"; //for testing
            $dom_arr[$d++] = $fields[2]; //assign ns to array index
            $m=1;//helps to control of which next lines of that domain to read and get the NSs
            //continue;
        }

        if( ($m==1) && preg_match("/^$/",trim($blank)) ){
            //for($i=0;$i<$d;$i++){
            //  echo $dom_arr[$i]."<br/><br/>";
            break;//} //controls where to stop reading the NS of the domain
          }
        if( ( $m==1)&& (preg_match("/^$/",trim($fields[0])) ) ){ //get NSs of the domain same as above
            //echo $fields[2]."<br/>"; //for testing
            $dom_arr[$d++] = $fields[2]; //assign ns to array index
            //continue;
            }   
        //*************display the name servers and write them to a file**************//
        echo "<br/>";
        echo "NSs of domain $domain:<br/>";
        for($i=0;$i<$d;$i++){ //print out the found NSs
            echo $dom_arr[$i]."<br/>";
            $fields = "$domain.mw, $dom_arr[$i], 'n";
             fwrite($fh,$fields);  //add the domains and expiry the to file
             break; //break each for loop
        }
    }
    fclose($fp); //close the final trimed zone file

}//end of while loop for file containing all domains
fclose($domains); //close the file containing all domains

Some One在这个链接上发布了一个类似的问题。返回域php的名称服务器数组,但我们使用的逻辑完全不同,这就是为什么我再次提问。

我可以看到这个脚本可能存在的两个问题:

  1. fopen($regfile,'a')将打开一个文件进行写入,将内部指针放在文件的。尝试使用fopen($regfile,'r+'),它会将指针放在文件的*开头。

  2. 当主机名中出现"空白"时,您会中断while循环,这将使循环停止。代码中没有任何内容允许脚本再次开始循环。

考虑使用continue语句而不是break,这将在标记点停止循环,但允许它从列表中的下一个项目再次继续循环。

首先,我们用file()将所有域放入一个数组中。然后,我们用array_map()在每个域上循环,并用rtrim()删除域末尾的逗号。所以我们得到了一个$domains数组,如下所示:

Array
(
    [0] => 000
    [1] => 1
    [2] => 10
    [3] => 101domain
    [4] => 11
)

之后,我们得到名称服务器文件作为字符串file_get_contents()。然后,我们用preg_split()将这个字符串拆分2行或更多新行,这样我们就可以在一个数组元素中获得每个域的所有名称服务器。

但是,每个域的名称服务器的格式并不是很方便。因此,我们在数组上循环,首先获得具有substr()的域,其中我们获得从元素开始到第一次出现NS的子字符串,其中我们使用strpos()获得位置,其次我们获得所有具有preg_match_all()的名称服务器,其中我们获取NS之后的所有名称。然后我们有了$nameservers数组,格式很方便,比如

Array (
    domain => Array(nameserver1, nameserver2, ...),
    //...
)

现在我们只需要通过键得到两个数组$domains$nameservers的交集,这可以很容易地用array_intersect_key()来完成。

最后,唯一要做的就是在交叉点上循环,并将数据保存为file_put_contents()格式。

代码

<?php
    $domains = array_map(function($v){
        return rtrim($v, ",");
    }, file("test.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES));
    $nameserversTmp = preg_split("/(?='R's*'R)['R's]+/", file_get_contents("test2.txt"));
    $nameservers = [];
    foreach($nameserversTmp as $nameserver){
        $domain = substr($nameserver, 0, strpos($nameserver, " NS"));
        preg_match_all("/NS (['w.]+)/", $nameserver, $m);
        $nameservers[$domain] = $m[1];
    }
    $intersect = array_intersect_key($nameservers, array_flip($domains));
    foreach($intersect as $domain => $nameserverList){
        file_put_contents("final.txt", $domain . ".mw, " . implode(", " . PHP_EOL . $domain . ".mw, ", $nameserverList) . PHP_EOL, FILE_APPEND);
    }
?>