PHP:如何正确使用 Strpos() 在字符串中查找单词
PHP: How to Properly Use Strpos() to Find a Word in a String
如果对 PHP 有经验,那么就会知道如何使用正则表达式和 preg_match() 或 preg_match_all 查找字符串中的整个单词及其位置。但是,如果您正在寻找更轻便的解决方案,您可能会想尝试使用 strpos()。问题是如何在不检测包含在其他单词中的子字符串的情况下使用此函数。例如,如何检测 "any" 而不是 "company"?
中出现的那些字符
考虑如下字符串:
"Will *any* company do *any* job, (are there any)?"
如何应用 strpos() 来检测字符串中 "any" 的每次出现?现实生活中通常涉及的不仅仅是 space 个分隔的单词。不幸的是,这句话在我最初发布时并没有出现非字母字符。
<?php
$subject = "any";
$b = " ";
$delimited = "$b$subject$b";
$replace = array("?","*","(",")",",",".");
$str = "Will *any* company do *any* job, (are there any)?";
echo "\nThe string: \"$str\"";
$temp = str_replace($replace,$b,$str);
while ( ($pos = strpos($temp,$delimited)) !== false )
{
echo "\nThe subject \"$subject\" occurs at position ",($pos + 1);
for ($i=0,$max=$pos + 1 + strlen($subject); $i <= $max; $i++) {
$temp[$i] = $b;
}
}
见demo
脚本将单词边界定义为空白space。如果字符串中有非字母字符,则将它们替换为空白 space,并将结果存储在 $temp
中。当循环迭代并检测到 $subject
时,它的每个字符都会变成 space,以便定位主题的下一次出现。考虑到所涉及的工作量,人们可能想知道与使用带有 preg_ 函数的正则表达式相比,这样的努力是否真的有回报。这是一个人必须自己决定的事情。我的目的是展示 如何 这可以使用 strpos() 来实现,而无需求助于提倡使用正则表达式的 SO 的经常重复的传统智慧。
如果您不愿意创建非字母字符的替换数组,有一个选项,如下所示:
<?php
function getAllWholeWordPos($s,$word){
$b = " ";
$delimited = "$b$word$b";
$retval = false;
for ($i=0, $max = strlen( $s ); $i < $max; $i++) {
if ( !ctype_alpha( $s[$i] ) ){
$s[$i] = $b;
}
}
while ( ( $pos = stripos( $s, $delimited) ) !== false ) {
$retval[] = $pos + 1;
for ( $i=0, $max = $pos + 1 + strlen( $word ); $i <= $max; $i++) {
$s[$i] = $b;
}
}
return $retval;
}
$whole_word = "any";
$str = "Will *$whole_word* company do *$whole_word* job, (are there $whole_word)?";
echo "\nString: \"$str\"";
$result = getAllWholeWordPos( $str, $whole_word );
$times = count( $result );
echo "\n\nThe word \"$whole_word\" occurs $times times:\n";
foreach ($result as $pos) {
echo "\nPosition: ",$pos;
}
见demo
请注意,此示例及其更新通过提供使用 strpos() 变体的函数改进了代码,即 stripos(),它具有不区分大小写的额外好处。尽管需要更多的劳动密集型编码,但性能还是很快的;参见 performance。
试试下面的代码
<!DOCTYPE html>
<html>
<body>
<?php
echo strpos("I love php, I love php too!","php");
?>
</body>
</html>
Output: 7
我认为您可以只删除所有您关心的空白字符(例如,连字符呢?)并测试 " word "
:
var_dump(firstWordPosition('Will company any do any job, (are there any)?', 'any'));
var_dump(firstWordPosition('Will *any* company do *any* job, (are there any)?', 'any'));
function firstWordPosition($str, $word) {
// There are others, maybe also pass this in or array_merge() for more control.
$nonchars = ["'",'"','.',',','!','?','(',')','^','$','#','\n','\r\n','\t',];
// You could also do a strpos() with an if and another argument passed in.
// Note that we're padding the $str to with spaces to match begin/end.
$pos = stripos(str_replace($nonchars, ' ', " $str "), " $word ");
// Have to account for the for-space on " $str ".
return $pos ? $pos - 1: false;
}
给出 12(从 0 偏移)
如果对 PHP 有经验,那么就会知道如何使用正则表达式和 preg_match() 或 preg_match_all 查找字符串中的整个单词及其位置。但是,如果您正在寻找更轻便的解决方案,您可能会想尝试使用 strpos()。问题是如何在不检测包含在其他单词中的子字符串的情况下使用此函数。例如,如何检测 "any" 而不是 "company"?
中出现的那些字符考虑如下字符串:
"Will *any* company do *any* job, (are there any)?"
如何应用 strpos() 来检测字符串中 "any" 的每次出现?现实生活中通常涉及的不仅仅是 space 个分隔的单词。不幸的是,这句话在我最初发布时并没有出现非字母字符。
<?php
$subject = "any";
$b = " ";
$delimited = "$b$subject$b";
$replace = array("?","*","(",")",",",".");
$str = "Will *any* company do *any* job, (are there any)?";
echo "\nThe string: \"$str\"";
$temp = str_replace($replace,$b,$str);
while ( ($pos = strpos($temp,$delimited)) !== false )
{
echo "\nThe subject \"$subject\" occurs at position ",($pos + 1);
for ($i=0,$max=$pos + 1 + strlen($subject); $i <= $max; $i++) {
$temp[$i] = $b;
}
}
见demo
脚本将单词边界定义为空白space。如果字符串中有非字母字符,则将它们替换为空白 space,并将结果存储在 $temp
中。当循环迭代并检测到 $subject
时,它的每个字符都会变成 space,以便定位主题的下一次出现。考虑到所涉及的工作量,人们可能想知道与使用带有 preg_ 函数的正则表达式相比,这样的努力是否真的有回报。这是一个人必须自己决定的事情。我的目的是展示 如何 这可以使用 strpos() 来实现,而无需求助于提倡使用正则表达式的 SO 的经常重复的传统智慧。
如果您不愿意创建非字母字符的替换数组,有一个选项,如下所示:
<?php
function getAllWholeWordPos($s,$word){
$b = " ";
$delimited = "$b$word$b";
$retval = false;
for ($i=0, $max = strlen( $s ); $i < $max; $i++) {
if ( !ctype_alpha( $s[$i] ) ){
$s[$i] = $b;
}
}
while ( ( $pos = stripos( $s, $delimited) ) !== false ) {
$retval[] = $pos + 1;
for ( $i=0, $max = $pos + 1 + strlen( $word ); $i <= $max; $i++) {
$s[$i] = $b;
}
}
return $retval;
}
$whole_word = "any";
$str = "Will *$whole_word* company do *$whole_word* job, (are there $whole_word)?";
echo "\nString: \"$str\"";
$result = getAllWholeWordPos( $str, $whole_word );
$times = count( $result );
echo "\n\nThe word \"$whole_word\" occurs $times times:\n";
foreach ($result as $pos) {
echo "\nPosition: ",$pos;
}
见demo
请注意,此示例及其更新通过提供使用 strpos() 变体的函数改进了代码,即 stripos(),它具有不区分大小写的额外好处。尽管需要更多的劳动密集型编码,但性能还是很快的;参见 performance。
试试下面的代码
<!DOCTYPE html>
<html>
<body>
<?php
echo strpos("I love php, I love php too!","php");
?>
</body>
</html>
Output: 7
我认为您可以只删除所有您关心的空白字符(例如,连字符呢?)并测试 " word "
:
var_dump(firstWordPosition('Will company any do any job, (are there any)?', 'any'));
var_dump(firstWordPosition('Will *any* company do *any* job, (are there any)?', 'any'));
function firstWordPosition($str, $word) {
// There are others, maybe also pass this in or array_merge() for more control.
$nonchars = ["'",'"','.',',','!','?','(',')','^','$','#','\n','\r\n','\t',];
// You could also do a strpos() with an if and another argument passed in.
// Note that we're padding the $str to with spaces to match begin/end.
$pos = stripos(str_replace($nonchars, ' ', " $str "), " $word ");
// Have to account for the for-space on " $str ".
return $pos ? $pos - 1: false;
}
给出 12(从 0 偏移)