我正在处理一些文本文件,想要找到某些标记,还需要一些围绕它们的文本来获取上下文。 我的问题是,如果标记的每个实例都足够接近,无法被其前面的标记上下文捕获,我就找不到它。
作为示例和简化,假设我想在某些文本中找到每个5位数字,并在其前后分别找到20个字符以获取上下文。
首先,我尝试过类似的操作:
<?php
$text = "Lorem ipsum 11111 dolor sit 22222 amet, consectetur 33333 adipiscing elit, sed do eiusmod tempor 1111 incididunt ut 11111 labore et dolore magna aliqua.";
$nmbrs_tmp = array();
preg_match_all("@.{0,19}[^\d](\d{5})[^\d].{0,19}@s", $text, $nmbrs_tmp);
print_r($nmbrs_tmp);
但是它不会捕获22222,因为它已经在11111的第一次捕获之内并且是上下文:
//output Array ( [0] => Array ( [0] => Lorem ipsum 11111 dolor sit 22222 ame [1] => t, consectetur 33333 adipiscing elit, se [2] => 1111 incididunt ut 11111 labore et dolore ma ) [1] => Array ( [0] => 11111 [1] => 33333 [2] => 11111 ) )
然后我尝试了先行和后退,但第1次:lookbehinds必须为固定长度,第2次:我不再捕获上下文了:"@(?<=.{0,19})[^\d](\d{5})[^\d](?=.{0,19})@s" //this won't work
理想情况下,我会喜欢这样的东西,在这里我捕获每个5位数字的实例,并获得所有可能的上下文:
//output Array ( [0] => Array ( [0] => Lorem ipsum 11111 dolor sit 22222 ame [1] => sum 11111 dolor sit 22222 amet, consectetur 3 [2] => 2 amet, consectetur 33333 adipiscing elit, se [3] => 1111 incididunt ut 11111 labore et dolore ma ) [1] => Array ( [0] => 11111 [1] => 22222 [2] => 33333 [3] => 11111 ) )
如果没有办法使用正则表达式来做到这一点,那么我愿意接受涉及多次阅读文本或使用更多正则表达式的PHP解决方案。
答案 0 :(得分:0)
这是一种使用匹配偏移量来计算相关子字符串的方法:
<?php
$text = "99999 Lorem ipsum 11111 dolor sit 22222 amet, consectetur 33333 adipiscing elit, sed do eiusmod tempor 1111 incididunt ut 11111 labore et dolore magna aliqua. 99999";
$nmbrs_tmp = array();
preg_match_all("@\b\d{5}\b@s", $text, $nmbrs_tmp, PREG_OFFSET_CAPTURE);
foreach ($nmbrs_tmp[0] as $key => $field) {
$offset = $field[1];
$start = ( $offset>=20 ? $offset-20 : 0 );
$length = $offset>=20 ? 45 : 45-(20-$offset);
$nmbrs_tmp[0][$key][2] = substr( $text, $start, $length );
}
print_r($nmbrs_tmp);
首先,我们将正则表达式简化为仅查找5位数字(您原来的正则表达式会在行首和末尾丢失数字)。
然后我们进行匹配,并传递PREG_OFFSET_CAPTURE标志。
最后,我们使用返回的偏移量来计算所需子字符串的长度($length
是否落在输入的末尾可能并不重要,但您可以根据需要进行调整)。
结果是:
Array
(
[0] => Array
(
[0] => Array
(
[0] => 99999
[1] => 0
[2] => 99999 Lorem ipsum 11111 d
)
[1] => Array
(
[0] => 11111
[1] => 18
[2] => 99999 Lorem ipsum 11111 dolor sit 22222 ame
)
[2] => Array
(
[0] => 22222
[1] => 34
[2] => sum 11111 dolor sit 22222 amet, consectetur 3
)
[3] => Array
(
[0] => 33333
[1] => 58
[2] => 2 amet, consectetur 33333 adipiscing elit, se
)
[4] => Array
(
[0] => 11111
[1] => 122
[2] => 1111 incididunt ut 11111 labore et dolore ma
)
[5] => Array
(
[0] => 99999
[1] => 159
[2] => olore magna aliqua. 99999
)
)
)