如何使用开始和结束单词数组查找字符串中的所有子字符串 PHP
How to find ALL substrings in string using starting and ending words arrays PHP
我花了最后 4 个小时弄清楚如何......我现在必须寻求你的帮助。
我正在尝试从文本中提取多个子字符串匹配我的 starting_words_array 和 ending_words_array。
$str = "Do you see that ? Indeed, I can see that, as well as this." ;
$starting_words_array = array('do','I');
$ending_words_array = array('?',',');
预期输出:数组([0] => 'Do you see that ?' [1] => 'I can see that,')
我设法编写了第一个函数,它可以找到与两个数组项之一匹配的第一个子字符串。但是我找不到如何循环它以获得符合我要求的所有子字符串。
function SearchString($str, $starting_words_array, $ending_words_array ) {
forEach($starting_words_array as $test) {
$pos = strpos($str, $test);
if ($pos===false) continue;
$found = [];
forEach($ending_words_array as $test2) {
$posStart = $pos+strlen($test);
$pos2 = strpos($str, $test2, $posStart);
$found[] = ($pos2!==false) ? $pos2 : INF;
}
$min = min($found);
if ($min !== INF)
return substr($str,$pos,$min-$pos) .$str[$min];
}
return '';
}
你们知道如何实现这样的事情吗?
我肯定会使用正则表达式和 preg_match_all()
。我不会在这里为您提供完整的工作代码示例,但我会概述必要的步骤。
首先,从您的 start-end-pairs 构建一个正则表达式,如下所示:
$parts = array_map(
function($start, $end) {
return $start . '.+' . $end;
},
$starting_words_array,
$ending_words_array
);
$regex = '/' . join('|', $parts) . '/i';
/i
部分表示搜索不区分大小写。 ?
等某些字符在正则表达式中有特殊用途,因此您需要扩展上述函数才能正确转义它。
您可以测试最终的正则表达式 here
然后使用preg_match_all()
提取你的子串:
preg_match_all($regex, $str, $matches); // $matches is passed by reference, no need to declare it first
print_r($matches);
$matches 数组的确切结构与您要求的略有不同,但您可以从中提取所需的数据
Benni 的回答是最好的方法 - 但如果您想解决这些问题,请指出您代码中的问题:
strpos
不区分大小写,也可以找到部分单词,因此您需要将 $starting_words_array = array('do','I');
更改为 $starting_words_array = array('Do','I ');
- 查找子字符串时使用 return 退出函数,以便查找任何其他子字符串。为了解决这个问题,您可以在函数的开头定义
$res = [];
并将 return substr($str,$pos,...
替换为 $res[] = substr($str,$pos,...
并在结尾处 return 替换 $res
var.
您可以在 3v4l 中查看示例 - 在该示例中您将获得所需的输出
我使用 preg_match 作为我的解决方案。但是,开始和结束字符串必须使用 preg_quote 进行转义。否则,解决方案将是错误的。
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr[] = $match[0];
}
}
return $resArr;
}
结果是提问者所期望的
如果表达式可以出现多次,则还必须使用 preg_match_all。必须修改正则表达式。
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*?".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr = array_merge($resArr,$match[0]);
}
}
return $resArr;
}
第二种变体的结果:
array (
0 => "Do you see that ?",
1 => "Indeed,",
2 => "I can see that,",
)
我花了最后 4 个小时弄清楚如何......我现在必须寻求你的帮助。
我正在尝试从文本中提取多个子字符串匹配我的 starting_words_array 和 ending_words_array。
$str = "Do you see that ? Indeed, I can see that, as well as this." ;
$starting_words_array = array('do','I');
$ending_words_array = array('?',',');
预期输出:数组([0] => 'Do you see that ?' [1] => 'I can see that,')
我设法编写了第一个函数,它可以找到与两个数组项之一匹配的第一个子字符串。但是我找不到如何循环它以获得符合我要求的所有子字符串。
function SearchString($str, $starting_words_array, $ending_words_array ) {
forEach($starting_words_array as $test) {
$pos = strpos($str, $test);
if ($pos===false) continue;
$found = [];
forEach($ending_words_array as $test2) {
$posStart = $pos+strlen($test);
$pos2 = strpos($str, $test2, $posStart);
$found[] = ($pos2!==false) ? $pos2 : INF;
}
$min = min($found);
if ($min !== INF)
return substr($str,$pos,$min-$pos) .$str[$min];
}
return '';
}
你们知道如何实现这样的事情吗?
我肯定会使用正则表达式和 preg_match_all()
。我不会在这里为您提供完整的工作代码示例,但我会概述必要的步骤。
首先,从您的 start-end-pairs 构建一个正则表达式,如下所示:
$parts = array_map(
function($start, $end) {
return $start . '.+' . $end;
},
$starting_words_array,
$ending_words_array
);
$regex = '/' . join('|', $parts) . '/i';
/i
部分表示搜索不区分大小写。 ?
等某些字符在正则表达式中有特殊用途,因此您需要扩展上述函数才能正确转义它。
您可以测试最终的正则表达式 here
然后使用preg_match_all()
提取你的子串:
preg_match_all($regex, $str, $matches); // $matches is passed by reference, no need to declare it first
print_r($matches);
$matches 数组的确切结构与您要求的略有不同,但您可以从中提取所需的数据
Benni 的回答是最好的方法 - 但如果您想解决这些问题,请指出您代码中的问题:
strpos
不区分大小写,也可以找到部分单词,因此您需要将$starting_words_array = array('do','I');
更改为$starting_words_array = array('Do','I ');
- 查找子字符串时使用 return 退出函数,以便查找任何其他子字符串。为了解决这个问题,您可以在函数的开头定义
$res = [];
并将return substr($str,$pos,...
替换为$res[] = substr($str,$pos,...
并在结尾处 return 替换$res
var.
您可以在 3v4l 中查看示例 - 在该示例中您将获得所需的输出
我使用 preg_match 作为我的解决方案。但是,开始和结束字符串必须使用 preg_quote 进行转义。否则,解决方案将是错误的。
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr[] = $match[0];
}
}
return $resArr;
}
结果是提问者所期望的
如果表达式可以出现多次,则还必须使用 preg_match_all。必须修改正则表达式。
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*?".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr = array_merge($resArr,$match[0]);
}
}
return $resArr;
}
第二种变体的结果:
array (
0 => "Do you see that ?",
1 => "Indeed,",
2 => "I can see that,",
)