我有一个文本文件(实际上是一个区域文件),如下所示:
...
;
; base config
; -----------------------------------------------------------------
@ 14400 IN A 1.2.3.4
@ 14400 IN AAAA 1:2:3::4
;
; mail config
; -----------------------------------------------------------------
mail 14400 IN A 1.2.3.4
mail 14400 IN AAAA 1:2:3::4
@ 14400 IN MX 10 mail.example.com.
;
; www config
; -----------------------------------------------------------------
www 14400 IN CNAME example.com.
...
我想将每个没有注释掉的行解析为数组,逐块。所以看起来应该是这样的:
$array = array(
"base" => array(
"0" => "@ 14400 IN A 1.2.3.4",
"1" => "@ 14400 IN AAAA 1:2:3::4"
),
"mail" => array (
"0" => "mail 14400 IN A 1.2.3.4",
"1" => "mail 14400 IN AAAA 1:2:3::4",
"1" => "@ 14400 IN MX 10 mail.example.com."
),
"www" => array(
"0" => "www 14400 IN CNAME example.com."
)
);
在这种情况下,评论是“;”所以它根本不需要解析。注释掉的部分是修复的,比如“基本配置”和“邮件配置”,而“www配置”没有改变,它每次都像我的例子一样。但是每个块中的记录(未通过;省略)可能会发生变化,因此可能只有1条记录,或5,10或任何记录。我试着把文本文件放到一个数组中,用foreach循环处理它,然后用preg_match()搜索相应的行但是它没有解决,因为我不知道有多少记录(行)到来文件的下一部分。她是我的尝试:
<?php
// Get lines
$lines = file('file.txt');
// Loop through our array
foreach ($lines as $line_num => $line) {
if (preg_match("/\bbase config\b/i", $line)) {
$line++
// I don't know how to continue and find the next section
}
}
?>
如果你可以帮助我处理一个区块(基地,邮件或www),它会对我有所帮助,基于此,我可以解决其他问题。
答案 0 :(得分:2)
使用foreach()
,您可以检查第一行是否以;
开头,并检查该行的内容是否为配置名称。您可以使用trim()
和list()
来检查该行的内容:
$lines = file('file.txt');
$config = '';
$array = []; // outputs array:
foreach ($lines as $line) {
if (strpos($line, ';') === 0) { // if starts with ';'
$line = trim($line, '-; '); // remove unwanted characters
if (!$line) continue; // if empty, it's an unwanted line
list($config) = explode(' ', $line, 2); // get the config name
continue;
}
$array[$config][] = $line; // store line in config array
}
print_r($array);
输出:
Array
(
[base] => Array
(
[0] => @ 14400 IN A 1.2.3.4
[1] => @ 14400 IN AAAA 1:2:3::4
)
[mail] => Array
(
[0] => mail 14400 IN A 1.2.3.4
[1] => mail 14400 IN AAAA 1:2:3::4
[2] => @ 14400 IN MX 10 mail.example.com.
)
[www] => Array
(
[0] => www 14400 IN CNAME example.com.
)
)
答案 1 :(得分:2)
另一种解决方案
<?php
$filepath = __DIR__ . '/file.txt';
$validSection = false;
$startingSectionPattern = '/^; [a-z]+ config$/i';
$startingSections = ['base' => '; base config', 'mail' => '; mail config', 'www' => '; www config'];
$res = [];
foreach (file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
if ($line[0] == ';' && preg_match($startingSectionPattern, $line)) {
$validSection = false;
$key = array_search($line, $startingSections);
if ($key !== false) {
$validSection = true;
}
}
if ($validSection && $line[0] != ';') {
$res[$key][] = $line;
}
}
var_dump($res);
答案 2 :(得分:1)
备注:强>
我已经更新了这个答案,只是为了让它完全正常运行。现在它处理所有配置选项。
此示例使用“基于表格”的方法并逐行读取文件。换行符char(chars)包含在$ output中。
zones.txt
;
; base config
; -----------------------------------------------------------------
@ 14400 IN A 1.2.3.4
@ 14400 IN AAAA 1:2:3::4
;
; mail config
; -----------------------------------------------------------------
mail 14400 IN A 1.2.3.4
mail 14400 IN AAAA 1:2:3::4
@ 14400 IN MX 10 mail.example.com.
;
; www config
; -----------------------------------------------------------------
www 14400 IN CNAME example.com.
;
zones.php
<?php
$output = array();
$configName = '';
$configFound = false;
$handle = fopen("zones.txt", "r");
if ($handle) {
while (!feof($handle)) {
$row = fgets($handle);
if (substr($row, 0, 1) == ';') {
if (strpos($row, "config") === false) {
$configFound = false;
} else {
$configFound = true;
$configName = $row;
$configName = str_replace(' ', '', $configName);
$configName = str_replace(';', '', $configName);
$configName = str_replace('config', '', $configName);
}
} else {
$output[$configName][] = $row;
}
}
fclose($handle);
}
var_dump($output);
?>