2010-05-01 84 views
2

比方说,我有这样的输入:应用PHP正则表达式替换多行的重复模式

I can haz a listz0rs! 
# 42 
# 126 
I can haz another list plox? 
# Hello, world! 
# Welcome! 

我想分割它,这样每组散列开始行变成一个列表:

I can haz a listz0rs! 
<ul> 
    <li>42</li> 
    <li>126</li> 
</ul> 
I can haz another list plox? 
<ul> 
    <li>Hello, world!</li> 
    <li>Welcome!</li> 
</ul> 

如果我跑对正则表达式中输入 “(。*)/(???:(:(< = ^#)$)+)/ M”,我得到以下结果:

Array 
(
    [0] => Array 
    (
     [0] => 42 
    ) 
    [1] => Array 
    (
     [0] => 126 
    ) 
    [2] => Array 
    (
     [0] => Hello, world! 
    ) 
    [3] => Array 
    (
     [0] => Welcome! 
    ) 
) 

这很好,很花哨,但它没有区分两个不同的列表。我需要一种方法来让量词返回所有出现的连接字符串,或者理想情况下是所有出现的数组。

理想的情况下,这应该是我的输出:

Array 
(
    [0] => Array 
    (
     [0] => 42 
     [1] => 126 
    ) 
    [1] => Array 
    (
     [0] => Hello, world! 
     [1] => Welcome! 
    ) 
) 

是否有实现这一目标的任何方式,如果没有,是否有一个密切的选择吗?

回答

1

如果你想用正则表达式来做到这一点,你需要两个。使用正则表达式^(#.*\r?\n)+来匹配每个列表并在其周围添加标签。在每个列表中(与第一个正则表达式匹配),搜索并替换^#.*<li>$0</li>以在每个列表项目周围添加标签。这两个正则表达式都需要^以换行符(PHP中的/m标志)匹配。

在PHP中,您可以使用preg_replace_callbackpreg_replace在几行代码中实现。

$result = preg_replace_callback('/^(#.*\r?\n)+/m', 'replacelist', $subject); 

function replacelist($groups) { 
    return "<ul>\n" . 
    preg_replace('/^#.*/m', ' <li>$0</li>', $groups[0]) 
    . "</ul>\n"; 
} 
0

我想说,不要试图在一个正则表达式中完成所有操作 - 相反,首先使用正则表达式来匹配连续行集合,这些连续行集都以#标志开头,并用<ul></ul>对包装这些行。然后使用第二个正则表达式(甚至根本不需要正则表达式 - 您可以在换行符上分割)来匹配每条单独的行,并将其转换为<li></li>格式。

+0

我想过这样做,但问题是,你不能量化行,所以当你把它们包装在ul标签中时,你将包装*每行*而不是整个集合。 – Hussain 2010-05-01 04:55:11

+0

使用多行正则表达式,您可以一次匹配多行。你只需要匹配它们之间的空格换行符。 – Amber 2010-05-01 19:54:12

0

如果是我,我会:

  1. 爆炸( “\ n”,$输入)到一个数组,其中1个键=行的foreach通过阵列
  2. 每当你得到一个线不是以#开始,那是当你添加你的关闭/打开ul标记

添加一些处理意外输入(如连续两个非哈希线),你很好。

0

你可以完全避免使用regex,只需通过逐行读取文件(一行数组)就可以尝试更简单的方法,并且每次遇到非哈希启动的行时,它都会启动一个新的名单。像这样:

// You can get this by using file('filename') or 
// just doing an explode("\n", $input) 
$lines = array(
    'I can haz a listz0rs!', 
    '# 42', 
    '# 126', 
    'I can haz another list plox?', 
    '# Hello, world!', 
    '# Welcome!' 
); 

$hashline = false; 
$lists = array(); 
$curlist = array(); 
foreach ($lines as $line) { 
    if ($line[0] == '#') 
     $curlist[] = $line; 
    elseif ($hashline) { 
     $lists[] = $curlist; 
     $curlist = array(); 
     $hashline = false; 
    } 
} 

一些清理可能是为了,但希望它可以帮助。

(读出新的答案后,这基本上是语法错误的回答的深入解释。)

编辑:您可能希望它在每一行的开头太剥去#。

0

像这样的结构化内容,我不会这样做的正则表达式。另一种方法呢?

$your_text = <<<END 
I can haz a listz0rs! 
# 42 
# 126 
I can haz another list plox? 
# Hello, world! 
# Welcome! 
END; 

function printUnorderedList($temp) { 
    if (count($temp)>0) { 
     print "<ul>\n\t<li>" .implode("</li>\n\t<li>", $temp) . "</li>\n</ul>\n"; 
    } 
} 

$lines = explode("\n", $your_text); 
$temp = array(); 
foreach($lines as $line) { 
    if (substr($line, 0, 1) == '#') { 
     $temp[] = trim(substr($line,1)); 
    } else { 
     printUnorderedList($temp); 
     $temp = array(); 
     echo $line . "\n"; 
    } 
} 
printUnorderedList($temp);