iT邦幫忙

0

【陣列中取出字串來比對???】

我有一個陣列如下
這個陣列有2行是我要比對的字串
Circuit $l_s_p vlan-id $l_v
ip address $stb_ip (applied)
然後我也提供了上面2行的3個參數值
$l_s_p = 5/1(和陣列字串一樣)
$l_v = 1250(和陣列字串不一樣)
$stb_ip = 10.153.167.155(和陣列字串不一樣)
請問要怎麼寫讓它可以知道說
其實陣列中的
1338

10.153.167.161
是錯的
也就是要先從陣列中
抓出關鍵的那2行出來
然後和參數再進行比對
請大家指教
謝謝大家

<?php
$a = array('Circuit   5/1 vlan-id 1338',
        'Internal Circuit   5/1:1023:63/1/2/4136',
        'Interface bound  mod-gw',
        'Current port-limit unlimited',
        'ip address 10.153.167.161 (applied)',
        'profile 1xSTB (applied)',
        'ip source-validation 1 (applied from sub_profile)',
        'ip access-group in adsl-acl (applied from sub_profile)',
        'qos-policing-policy vod-mark (applied from sub_profile)',
        'qos-metering-policy vod-meter (applied from sub_profile)',
        'timeout idle 36000 (applied from sub_default)'
);
?>

2 個回答

2
weiclin
iT邦高手 4 級 ‧ 2014-12-05 13:46:47
最佳解答
<pre class="c" name="code">
<?php

$a = array('Circuit   5/1 vlan-id 1338',
    'Internal Circuit   5/1:1023:63/1/2/4136',
    'Interface bound  mod-gw',
    'Current port-limit unlimited',
    'ip address 10.153.167.161 (applied)',
    'profile 1xSTB (applied)',
    'ip source-validation 1 (applied from sub_profile)',
    'ip access-group in adsl-acl (applied from sub_profile)',
    'qos-policing-policy vod-mark (applied from sub_profile)',
    'qos-metering-policy vod-meter (applied from sub_profile)',
    'timeout idle 36000 (applied from sub_default)'
);

$l_s_p = "5/1";
$l_v = "1250";
$stb_ip = "10.153.167.155";

// 方法1
$v1 = preg_grep("/^Circuit.*vlan-id/", $a);
$str1 = array_pop($v1);
if (false === strpos($str1, $l_s_p)) {
    echo "$l_s_p wrong\n";
}
if (false === strpos($str1, $l_v)) {
    echo "$l_v wrong\n";
}

$v2 = preg_grep("/^ip address.*(applied)/", $a);
$str2 = array_pop($v2);
if (false === strpos($str2, $stb_ip)) {
    echo "$stb_ip wrong\n";
}

// 方法2
$all = implode("\n", $a);
$found = preg_match("/^Circuit\s+(.+)\s+vlan-id\s+(\d+)$/m", $all, $matches);
if ($found) {
    if ($matches[1] !== $l_s_p) {
        echo "$l_s_p wrong\n";
    }
    if ($matches[2] !== $l_v) {
        echo "$l_v wrong\n";
    }
}

$found = preg_match("/^ip\s+address\s+(.+)\s+\(applied\)$/m", $all, $matches);
if ($found) {
    if ($matches[1] !== $stb_ip) {
        echo "$stb_ip wrong\n";
    }
}
看更多先前的回應...收起先前的回應...
andyto202 iT邦研究生 4 級 ‧ 2014-12-05 14:27:36 檢舉

weiclin 兄,謝謝你的回答
因為那個陣列算是在設備下指令其中的一個結果
所以我有可能針對不同的指令結果,設計不同的比對指令放到文字檔
例如把你的
^Circuit\s+(.+)\s+vlan-id\s+(\d+)$
^ip\s+address\s+(.+)\s+\(applied\)$
放在文字檔

andyto202 iT邦研究生 4 級 ‧ 2014-12-05 14:29:16 檢舉

剛按太快了,那如果假設這個是指令 a,所以產生陣列 a的結果
我存成 a.php 好了
那麼我在把你的
^Circuit\s+(.+)\s+vlan-id\s+(\d+)$
^ip\s+address\s+(.+)\s+\(applied\)$
存在 check_a.txt 好了
那麼要怎麼改寫你方法二的指令呢??

weiclin iT邦高手 4 級 ‧ 2014-12-06 03:59:05 檢舉

我不太懂你為什麼要把指令輸出的文字存為 .php 檔?
通常我是把輸出存成 .txt 檔, 再用程式去讀取 .txt 檔來分析結果

以你舉的例子, check_a.txt 裡面有兩條 regexp 規則, 總共會抓出三個數值
那是不是有可能 check_b.txt 裡面有四條規則, 共要抓出五筆數值?
於是你還得有另一個 php 程式去讀取 a.php 與 check_a.txt, 並且要知道怎樣用 check_a.txt 的規則?
還是你的 a.php 會去讀取 check_a.txt 的規則並輸出比對的結果?
php 其實挺自由的, 你講的都輕易做的到, 但邏輯上有些奇怪就是了

weiclin iT邦高手 4 級 ‧ 2014-12-06 04:11:28 檢舉

單純照你說的做, 就是這樣:
a.php:

<pre class="c" name="code"><?php

return array('Circuit   5/1 vlan-id 1338',
    'Internal Circuit   5/1:1023:63/1/2/4136',
    'Interface bound  mod-gw',
    'Current port-limit unlimited',
    'ip address 10.153.167.161 (applied)',
    'profile 1xSTB (applied)',
    'ip source-validation 1 (applied from sub_profile)',
    'ip access-group in adsl-acl (applied from sub_profile)',
    'qos-policing-policy vod-mark (applied from sub_profile)',
    'qos-metering-policy vod-meter (applied from sub_profile)',
    'timeout idle 36000 (applied from sub_default)'
);

check_a.txt

<pre class="c" name="code">^Circuit\s+(.+)\s+vlan-id\s+(\d+)$
^ip\s+address\s+(.+)\s+\(applied\)$
weiclin iT邦高手 4 級 ‧ 2014-12-06 04:12:08 檢舉

這個用來讀取 a.php 還有 check_a.txt 並顯示結果
result_a.php

<pre class="c" name="code"><?php

// read device ooutput
$a = require 'a.php';

// read regexp rules
$rules = file_get_contents("check_a.txt");
list($rule1, $rule2) = explode("\n", $rules);

// expected values
$l_s_p = "5/1";
$l_v = "1250";
$stb_ip = "10.153.167.155";

// start check
$all = implode("\n", $a);
$found = preg_match("/$rule1/m", $all, $matches);
if ($found) {
    if ($matches[1] !== $l_s_p) {
        echo "$l_s_p wrong\n";
    }
    if ($matches[2] !== $l_v) {
        echo "$l_v wrong\n";
    }
}

$found = preg_match("/$rule2/m", $all, $matches);
if ($found) {
    if ($matches[1] !== $stb_ip) {
        echo "$stb_ip wrong\n";
    }
}
andyto202 iT邦研究生 4 級 ‧ 2014-12-06 23:09:55 檢舉

$rules = file_get_contents("check_a.txt");
list($rule1, $rule2) = explode("\n", $rules);

weiclin 兄
照著你的做
結果竟然只顯示
10.153.167.155 wrong
1250 的沒顯示??

weiclin iT邦高手 4 級 ‧ 2014-12-07 02:08:42 檢舉

我這邊有顯示呀, 你再檢查一下吧

<pre class="c" name="code">
$ php result_a.php 
1250 wrong
10.153.167.155 wrong
andyto202 iT邦研究生 4 級 ‧ 2014-12-07 09:17:54 檢舉

我知道了
因為我是用 browser 執行的
你是用 cli 方式執行的
所以會不一樣

weiclin iT邦高手 4 級 ‧ 2014-12-07 12:21:22 檢舉

就算是browser, 頂多把 "\n" 換成 <br>就一樣了, 應該不會像你說的沒顯示

2
Old Siao
iT邦研究生 1 級 ‧ 2014-12-05 11:53:26

假如陣列內文字的值位置都一樣的話,運用PHP函式explode()把值取出來,在跟你的變數的值做比對即可
PHP explode():http://php.net/manual/en/function.explode.php

以下請參考一下:

&lt;pre class="c" name="code">
&lt;?php
header("Content-Type:text/html; charset=utf-8");

$a = array('Circuit   5/1 vlan-id 1338',
        'Internal Circuit   5/1:1023:63/1/2/4136',
        'Interface bound  mod-gw',
        'Current port-limit unlimited',
        'ip address 10.153.167.161 (applied)',
        'profile 1xSTB (applied)',
        'ip source-validation 1 (applied from sub_profile)',
        'ip access-group in adsl-acl (applied from sub_profile)',
        'qos-policing-policy vod-mark (applied from sub_profile)',
        'qos-metering-policy vod-meter (applied from sub_profile)',
        'timeout idle 36000 (applied from sub_default)'
);

$x=explode(" ",$a[0]);

echo "\$x陣列長度:".count($x)."&lt;br />";
for($i=0;$i&lt;count($x);$i++){
    echo "\$x[$i]=".$x[$i]."&lt;br />";
}
?>

看完題目突然想到的,應該有更好的方法,等待其他前輩的答案讚

我要發表回答

立即登入回答