preg_match_all与string中的数据不匹配

时间:2014-08-18 18:14:25

标签: php regex preg-replace

我实际上是在尝试提取仅以******为开头的行上的所有文字,而不是其他任何文字。低于或高于它。仅包含以******开头的行上的文字。

该数据来自表单中的textarea,如下所示:

*Heading 1*
User Text
**SubHeading 1A**
More UserText
***SubSubHeading 1AA***
More UserText
**SubHeading 1B**
More UserText
**Subheading 1C**
More UserText
**Subheading 1D**
More UserText
*Heading 2*
More UserText
**SubHeading 2A**
More UserText
**SubHeading 2B**
More UserText
**Subheading 2C**
More UserText
***Subheading 2C**
More UserText

最终结果是只得到这样的结果,而不是任何用户文本。

Heading 1
SubHeading 1A
SubSubHeading 1AA
SubHeading 1B
Subheading 1C
Subheading 1D
Heading 2
SubHeading 2A
SubHeading 2B
Subheading 2C
Subheading 2D

我修改了上一个答案,仅匹配以******开头的行,但我似乎没有得到任何结果,只是一个空白数组

if (preg_match_all('/^\*{1},{2},{3}([^\*].*)$/', $text, $matches))
        $result = array_map(function ($v) {
                return str_replace('*', ' ', rtrim($v, '*'));
        }, $matches[1]);

print_r($result);

我怎么能这样做才能得到我想要的结果?我无法想象我失败的地方。

3 个答案:

答案 0 :(得分:1)

你可以使用这个正则表达式:

$s = <<< EOF
*Heading 1*
User Text
**SubHeading 1A**
More UserText
***SubSubHeading 1AA***
More UserText
**SubHeading 1B**
More UserText
**Subheading 1C**
More UserText
**Subheading 1D**
More UserText
*Heading 2*
More UserText
**SubHeading 2A**
More UserText
**SubHeading 2B**
More UserText
**Subheading 2C**
More UserText
***Subheading 2D**
More UserText
EOF;
if ( preg_match_all('~^\*{1,3}(.+?)\*{1,3}$~m', $s, $m) )
   print_r($m[1]);

<强>输出:

Array
(
    [0] => Heading 1
    [1] => SubHeading 1A
    [2] => SubSubHeading 1AA
    [3] => SubHeading 1B
    [4] => Subheading 1C
    [5] => Subheading 1D
    [6] => Heading 2
    [7] => SubHeading 2A
    [8] => SubHeading 2B
    [9] => Subheading 2C
    [10] => Subheading 2D
)

答案 1 :(得分:1)

您可以使用此正则表达式:

\*+(.*?)\*+

<强> Working demo

MATCH 1
1.  [1-10]  `Heading 1`
MATCH 2
1.  [24-37] `SubHeading 1A`
MATCH 3
1.  [57-74] `SubSubHeading 1AA`
MATCH 4
1.  [94-107]    `SubHeading 1B`
MATCH 5
1.  [126-139]   `Subheading 1C`
MATCH 6
1.  [158-171]   `Subheading 1D`
MATCH 7
1.  [189-198]   `Heading 2`
MATCH 8
1.  [216-229]   `SubHeading 2A`
MATCH 9
1.  [248-261]   `SubHeading 2B`
MATCH 10
1.  [280-293]   `Subheading 2C`
MATCH 11
1.  [313-326]   `Subheading 2C`

答案 2 :(得分:0)

我建议将PCRE更改为'/(*ANYCRLF)^(\*{1,3})([^\*]+?)\1$/m'以消除上一个无效行(感谢'[^\*]')并确保不会为空结果数组在各种操作系统上(感谢'(*ANYCRLF)'官方PCRE选项修饰符 - 目前未在php.net上记录)具有不同的终点线(也就是换行符)字符("\r\n",{{1}或者甚至只是"\n")这样:

"\r"

这完全取决于数据的来源 - 外部和非受控源可能会提供非常混乱的数据。 对于那些试图打击(或至少解决)在多行模式(/ m)中任何行的末尾($)正确匹配模式的问题的提示。

<?php 
$str=<<<'STR'
*Heading 1*
User Text
**SubHeading 1A**
More UserText
***SubSubHeading 1AA***
More UserText
**SubHeading 1B**
More UserText
**Subheading 1C**
More UserText
**Subheading 1D**
More UserText
*Heading 2*
More UserText
**SubHeading 2A**
More UserText
**SubHeading 2B**
More UserText
**Subheading 2C**
More UserText
***Subheading 2C**
More UserText

STR;
$pat='/(*ANYCRLF)^(\*{1,3})(.+?)\1$/m';
$n=preg_match_all($pat, $str, $m);
// Your result is in $m[2] but take a look at the entire $m
echo ">>>\t\t1:\n$str\n($n) ".print_r($m, true)."\nResult WITH last invalid(?) row:\n".print_r($m[2], true);
// Last row contains invalid(?) number of stars (3 on the left and 2 on the right side)

$pat='/(*ANYCRLF)^(\*{1,3})([^\*]+?)\1$/m';
$n=preg_match_all($pat, $str, $m);
echo "\n>>>\t\t2:\n$str\n($n) ".print_r($m, true)."\nResult WITHOUT last invalid(?) row:\n".print_r($m[2], true);
// The last invalid row was eliminated
?>

不幸的是,我无法访问使用最新PHP版本的服务器 - 我的本地PHP为5.3.8,而我的公共主机PHP版本为5.2.17。