2012-10-30 22 views
1

我對PHP知之甚少,所以決定創建一個基於Web的工具來生成Red Hat kickstart文件將是一個很好的項目。除此之外,該工具將解析CSV文件並生成包含從中獲取的數據的表格。輸入文件格式如下:在PHP中創建任意行數的HTML表格

 
host1,10.153.196.248,255.255.255.0,10.153.196.1,00:50:56:ac:69:cb 
,10.153.157.113,255.255.255.128,10.153.157.1, 
,10.153.157.241,255.255.255.128,10.153.157.129, 
,/home,10,,, 
,swap,10,,, 
,/opt,60,,, 
,/data,30,,, 
,,,,, 
host2,10.153.155.124,255.255.255.128,10.153.155.1,00:50:56:ac:69:ce 
,10.153.157.114,255.255.255.128,10.153.157.1, 
,10.153.157.242,255.255.255.128,10.153.157.129, 
,/home,10,,, 
,swap,10,,, 
,/opt,60,,, 
,/data,30,,, 
,,,,, 

每段文本都代表一個服務器的信息。字段說明如下:

 
hostname,eth0 IP, eth0 netmask, eth0 gateway, eth4 MAC 
null,eth1 IP, eth1 netmask, eth1 gateway, null 
blank,eth2 IP, eth2 netmask, eth2 gateway, null 
null,partition name, partition size in GB, null, null 
null,partition name, partition size in GB, null, null 
null,partition name, partition size in GB, null, null 
null,partition name, partition size in GB, null, null 
null,null,null,null,null 

此刻,我可以分析它,併產生與輸入文件是在表中的行每行的表。產生

function processFile($workFile) { 

    if (file_exists($workFile)) { 
     print '<table>'; 
     $fh = fopen("$workFile", 'rb'); 
     if ($fh) { 
      for ($line = fgets($fh); !feof($fh); $line = fgets($fh)) { 
       $line = trim($line); 
       $info = explode(',', $line); 
       print '<tr><td>' . $info[0] . '</td><td>' . $info[1] . '</td><td>' . $info[2] . '</td><td>' . $info[3] . '</td></tr>'; 
      } 
     } else { 
      print "Failed to open $workFile"; 
     } 
     print '</table>'; 
    } else { 
     print "File $workFile does not exist"; 
    } 

} 

 
host1  eth0 IP  eth0 netmask  eth0 gateway 
      eth1 IP  eth1 netmask  eth1 gateway 
      eth2 IP  eth2 netmask  eth2 gateway 
      partition 1 partition 1 size 
      partition 2 partition 2 size 
      partition 3 partition 3 size 
      partition 4 partition 4 size 
host2  eth0 IP  eth0 netmask  eth0 gateway 
      eth1 IP  eth1 netmask  eth1 gateway 
      eth2 IP  eth2 netmask  eth2 gateway 
      partition 1 partition 1 size 
      partition 2 partition 2 size 
      partition 3 partition 3 size 
      partition 4 partition 4 size 

這是一個開始處理這個功能。但是,並不是每個服務器都有四個分區。有些會有更多,有些會少一兩個。事先並不知道這些信息會阻礙我想要做的事情,那就是在每個服務器的分區信息下面添加一行,並且可能會將每個服務器分解到自己的表中。沿此線的東西:

 
host1  eth0 IP   eth0 netmask  eth0 gateway 
      eth1 IP   eth1 netmask  eth1 gateway 
      eth2 IP   eth2 netmask  eth2 gateway 
      partition 1  partition 1 size 
      partition 2  partition 2 size 
      partition 3  partition 3 size 
      partition 4  partition 4 size 
      partition 5  partition 5 size 
      partition 6  partition 6 size 
      How many disks? [Text Field}  

host2  eth0 IP   eth0 netmask  eth0 gateway 
      eth1 IP   eth1 netmask  eth1 gateway 
      eth2 IP   eth2 netmask  eth2 gateway 
      partition 1  partition 1 size 
      partition 2  partition 2 size 
      partition 3  partition 3 size 
      partition 4  partition 4 size 
      How many disks? [Text Field} 

我當時的想法是,我將不得不在CSV文件中的字段表明該行包含分區信息。這似乎是最簡單的方法。我想知道是否有另一種方法可以使用,但不需要改變輸入文件的格式。

我還必須弄清楚如何使用包含所有空字段的行作爲分隔符。

任何想法如何我可以接近這將不勝感激。

+0

爲什麼不使用mysql數據庫呢? –

+0

也許是從其他來源導入數據 – Flosculus

+0

該工具的目的是獲取從現有電子表格創建並用於生成kickstart文件的CSV文件。文件生成後,CSV是不必要的。它可能會被保留用於考古目的,但除此之外,以數據庫的形式持續存在是過度的。如果CSV丟失,則可以通過電子表格重新創建CSV,如果再次需要,可能性不大。 – theillien

回答

0
echo('<table>'); 
$i = 0; 
while($data = fgetcsv($fh)) { 
    echo('<tr>'); 
    $cellTag = 'td'; 
    if($i == 0) { 
     $cellTag = 'th'; 
    } 
    $i++; 
    foreach($data as $cell) { 
     echo('<'.$cellTag.'>'.$cell.'</'.$cellTag.'>'); 
    } 
    echo('</tr>'); 
} 
echo('</table>'); 

試試看。勒米知道它是否第一次不起作用。我會測試它,但我沒有CSV文件。

+0

工作。雖然,我沒有註釋掉創建表頭的部分。我目前不擔心這一點。不過,我也需要能夠跳過MAC地址的顯示。否則,這似乎允許分區數據的任意行。謝謝。 – theillien

+0

現在我只需要弄清楚如何在允許輸入磁盤編號的主機數據的每個部分下面添加一行:'print'​​磁盤數量:​​」;' – theillien

+0

在StackOverflow中使用另一篇文章(http://stackoverflow.com/a/5040899/1602022)我想出瞭如何查找沒有條目的行,並使用它們來確定何時插入包含磁盤數量輸入字段的行。 – theillien

0

如你解析應該匹配特定格式的數據,應當在定期性質,允許你使用正則表達式來嚴格一致的你想要的輸入(並扔掉你不這樣做):

$rows = explode("\n", $input); 

// @link http://stackoverflow.com/questions/106179/regular-expression-to-match-hostname-or-ip-address 
$regIp = "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; 
$regHost = "(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])"; 

$hosts = array(); 
foreach ($rows as $row) { 
    $matches = null; 
    if (preg_match("/(?<host>$regHost),(?<ip>$regIp),(?<netmask>$regIp),(?<gateway>$regIp),(?<mac>.*)/", $row, $matches)) { 
    $host = $matches['host']; 
    $hosts[$host]['name'] = $matches['host']; 
    $hosts[$host]['mac'] = $matches['mac']; 
    $hosts[$host]['eth'][] = array(
     'ip'  => $matches['ip'], 
     'netmask' => $matches['netmask'], 
     'gateway' => $matches['gateway'], 
    ); 
    } else if (preg_match("/,(?<ip>$regIp),(?<netmask>$regIp),(?<gateway>$regIp),/", $row, $matches)) { 
    $hosts[$host]['eth'][] = array(
     'ip'  => $matches['ip'], 
     'netmask' => $matches['netmask'], 
     'gateway' => $matches['gateway'], 
    ); 
    } else if (preg_match("/,(?<name>.+),(?<size>\d+),,,/", $row, $matches)) { 
    $hosts[$host]['partition'][] = array(
     'name' => $matches['name'], 
     'size' => $matches['size'], 
    ); 
    } else if (preg_match("/,,,,,/", $row)) { 
    // we already partition output array with value of `$host` variable. 
    echo "Found terminating row\n"; 
    } else { 
    echo "Unrecognised data on row: $row\n"; 
    } 
} 

var_export($hosts); 

由於我們正在處理CSV文件,因此可以在循環內使用$fields = str_getcsv($row)來獲取包含每個字段的數組。然後需要計算該陣列有多少個字段,有多少個字段爲空,並驗證每個字段包含的內容。

直接在每個CSV行的字符串表示形式上使用正則表達式可以使我們在單個表達式中嚴格匹配上述所有內容。每個正則表達式的(?<var>...)部分被命名爲matches。使用由OP,上述腳本輸出所提供的輸入:

Found terminating row 
Found terminating row 
array (
    'host1' => 
    array (
    'name' => 'host1', 
    'mac' => '00:50:56:ac:69:cb', 
    'eth' => 
    array (
     0 => 
     array (
     'ip' => '10.153.196.248', 
     'netmask' => '255.255.255.0', 
     'gateway' => '10.153.196.1', 
    ), 
     1 => 
     array (
     'ip' => '10.153.157.113', 
     'netmask' => '255.255.255.128', 
     'gateway' => '10.153.157.1', 
    ), 
     2 => 
     array (
     'ip' => '10.153.157.241', 
     'netmask' => '255.255.255.128', 
     'gateway' => '10.153.157.129', 
    ), 
    ), 
    'partition' => 
    array (
     0 => 
     array (
     'name' => '/home', 
     'size' => '10', 
    ), 
     1 => 
     array (
     'name' => 'swap', 
     'size' => '10', 
    ), 
     2 => 
     array (
     'name' => '/opt', 
     'size' => '60', 
    ), 
     3 => 
     array (
     'name' => '/data', 
     'size' => '30', 
    ), 
    ), 
), 
    'host2' => 
    array (
    'name' => 'host2', 
    'mac' => '00:50:56:ac:69:ce', 
    'eth' => 
    array (
     0 => 
     array (
     'ip' => '10.153.155.124', 
     'netmask' => '255.255.255.128', 
     'gateway' => '10.153.155.1', 
    ), 
     1 => 
     array (
     'ip' => '10.153.157.114', 
     'netmask' => '255.255.255.128', 
     'gateway' => '10.153.157.1', 
    ), 
     2 => 
     array (
     'ip' => '10.153.157.242', 
     'netmask' => '255.255.255.128', 
     'gateway' => '10.153.157.129', 
    ), 
    ), 
    'partition' => 
    array (
     0 => 
     array (
     'name' => '/home', 
     'size' => '10', 
    ), 
     1 => 
     array (
     'name' => 'swap', 
     'size' => '10', 
    ), 
     2 => 
     array (
     'name' => '/opt', 
     'size' => '60', 
    ), 
     3 => 
     array (
     'name' => '/data', 
     'size' => '30', 
    ), 
    ), 
), 
) 

正如我們現在有適當的結構化數據的陣列,它應該是微不足道的輸出以任何所需的格式(即HTML表)中的數據。

+0

正則表達式路由似乎比必要的複雜得多。我已經能夠以我想要的格式輸出數據。我只需要知道如何爲每組分區使用任意數量的行。我會研究你關於str_getcsv()的建議。 – theillien