如何在 PHP 中获取句子的第一个单词?

Posted

技术标签:

【中文标题】如何在 PHP 中获取句子的第一个单词?【英文标题】:How to get the first word of a sentence in PHP? 【发布时间】:2011-01-29 10:13:52 【问题描述】:

我想从字符串中提取变量的第一个单词。例如,采用以下输入:

<?php $myvalue = 'Test me more'; ?>

结果输出应该是Test,这是输入的第一个字。 我该怎么做?

【问题讨论】:

您可能会发现 s($str)-&gt;words()[0] 很有帮助,如在 this standalone library 中找到的。 在第一次出现字符之前获取子字符串时的潜在边缘情况小表:***.com/a/68123370/2943403 【参考方案1】:

有一个字符串函数 (strtok) 可用于根据某些分隔符将字符串拆分为更小的字符串 (tokens)。就本线程而言,Test me more 的第一个单词(定义为第一个空格字符之前的任何内容)可以通过 tokenizing 空格字符上的字符串来获得。

<?php
$value = "Test me more";
echo strtok($value, " "); // Test
?>

有关更多详细信息和示例,请参阅strtok PHP manual page。

【讨论】:

太棒了!比原来的解决方案更好 这应该是第一个答案。它只会以更简洁的方式返回他想要的第一个单词。 很好的解决方案,但在 php 手册中,它警告:此函数可能返回 Boolean FALSE,但也可能返回计算结果为 FALSE 的非布尔值。 我每天都在使用 PHP 至少 6 年了,直到现在我才听说过这个功能 strtok 是一个奇怪而危险的函数,它拥有一个全局状态。不鼓励使用此功能。【参考方案2】:

您可以使用explode函数如下:

$myvalue = 'Test me more';
$arr = explode(' ',trim($myvalue));
echo $arr[0]; // will print Test

另一个例子:

$sentence = 'Hello World this is PHP';
$abbreviation = explode(' ', trim($sentence ))[0];
echo $abbreviation // will print Hello

【讨论】:

使用现代 PHP 语法你可以做到explode(' ',trim($myvalue))[0] 任何 PHP 版本的 1 行代码:list($firstword) = explode(' ', trim($myvalue), 1); @CédricFrançoys limit 参数应该是 2,因为它必须包含包含字符串其余部分的最后一个元素; 1 只会返回相同的字符串。除非创建一个大数组,否则我会使用 Elliot 版本的单衬。 如果您想要第二个词以及来自 RSS NewYorkTimes 的内容怎么办 - media:credit 是 - Dmitry Kostyukov for The New York Times 。我只想要 Dmitry Kostyukov - 我该怎么做? =) @xxxx,做explode(" ",strip_tags("&lt;media:credit&gt;Dmitry Kostyukov for The New York Times&lt;/media:credit&gt;"))[0]【参考方案3】:

如果你有 PHP 5.3

$myvalue = 'Test me more';
echo strstr($myvalue, ' ', true);

请注意,如果$myvalue 是一个包含一个单词的字符串,strstr 在这种情况下不会返回任何内容。一种解决方案可能是在测试字符串中附加一个空格:

echo strstr( $myvalue . ' ', ' ', true );

这将始终返回字符串的第一个单词,即使字符串中只有一个单词

替代方案类似于:

$i = strpos($myvalue, ' ');
echo $i !== false ? $myvalue : substr( $myvalue, 0, $i );

或者使用explode,它有很多答案,我不会费心指出如何去做。

【讨论】:

+1 表示不使用爆炸或正则表达式(恕我直言)。另一种选择是将 strstr 与 str_replace 一起使用,将 strstr 中针后的部分替换为空。 值得注意的是,虽然 strstr 在 PHP 中是可用的,因为 4.3.0 它不是在 5.3.0 之前,当可选参数 before_needle(你在这个例子中使用的)是添加。只是一个通知,因为我很困惑,为什么你说这个例子需要5.3.0 请注意,如果您将 myvalue 设置为单个单词 strstr 在这种情况下不会返回任何内容!一种解决方案可能是始终在测试的字符串末尾添加一个空格,以便它始终与第一个单词一起返回,即使这是字符串中唯一的单词! 假设单词之间只有空格是有风险的,我也会包括制表符。 不应该是echo $i === false ? $myvalue : substr( $myvalue, 0, $i );【参考方案4】:

你可以的

echo current(explode(' ',$myvalue));

【讨论】:

不起作用。试试这个字符串:“\n\nNextWord”。此答案假定所有单词仅由空格分隔。 原始问题的样本数据不包含任何前导换行符。【参考方案5】:

虽然有点晚了,但是 PHP 有一个更好的解决方案:

$words=str_word_count($myvalue, 1);
echo $words[0];

【讨论】:

【参考方案6】:

与接受的答案类似,只需少一步:

$my_value = 'Test me more';
$first_word = explode(' ',trim($my_value))[0];

//$first_word == 'Test'

【讨论】:

不起作用。试试这个字符串:“\n\nNextWord”。此答案假定所有单词仅由空格分隔。 是的,这确实假设“句子”是由空格分隔的单词构成的 我认为你没有抓住重点。我将单词中的“W”大写,以便您阅读。也许这对您来说更有意义 - “\n\n这行不通”。上面的代码会认为第一个单词是“\n\nThis” 这个迟到的、多余的、无法解释的答案错过了一个限制爆炸次数的好机会。【参考方案7】:

以防万一您不确定字符串是否以单词开头...

$input = ' Test me more ';
echo preg_replace('/(\s*)([^\s]*)(.*)/', '$2', $input); //Test

【讨论】:

trim($input) 在这种情况下就足够了:P 我不会捕获\s*。我不会写[^\s],因为\S 更简单。最后我不会捕获.*。对于这么小的sn-p,这个答案做了太多不必要的事情。【参考方案8】:
<?php
  $value = "Hello world";
  $tokens = explode(" ", $value);
  echo $tokens[0];
?>

只需使用explode获取输入的每个单词并输出结果数组的第一个元素。

【讨论】:

不起作用。试试这个字符串:“\n\nNextWord”。此答案假定所有单词仅由空格分隔。 这个答案不限制爆炸的数量,所以它可能做的工作比需要的要多。【参考方案9】:

使用 split 函数也可以从字符串中获取第一个单词。

<?php
$myvalue ="Test me more";
$result=split(" ",$myvalue);
echo $result[0];
?>

【讨论】:

注意 - split() 从 5.3 开始已弃用 > split() 没有限制,所以这种技术会过度使用。它只需要在第一个出现的空间爆炸即可正确完成工作。【参考方案10】:
$string = ' Test me more ';
preg_match('/\b\w+\b/i', $string, $result); // Test
echo $result;

/* You could use [a-zA-Z]+ instead of \w+ if wanted only alphabetical chars. */
$string = ' Test me more ';
preg_match('/\b[a-zA-Z]+\b/i', $string, $result); // Test
echo $result;

问候, 丘尔

【讨论】:

这将是最好的答案,因为它也适用于“一、二和三”(接受的答案会回显“一”) 如果字符类有[a-zA-Z] 或者如果您使用\w,为什么要使用i 模式修饰符?如果第一个“单词”包含撇号或连字符,输出应该是什么?深思熟虑。这个无法解释的答案是在教不必要的东西。【参考方案11】:

strtokextractpreg_* 函数更快。

【讨论】:

这个答案似乎更像是一个评论。它似乎试图权衡其他答案。我不知道extract() 在这里有什么用处。 preg_ 函数会更慢,但它们提供了更强大的技术,可以在边缘情况下清除不需要的字符。【参考方案12】: $input = "测试我更多"; echo preg_replace("/\s.*$/","",$input); // “测试”

【讨论】:

字符串元字符的 $ 结尾不是此模式正常工作所必需的。【参考方案13】:

个人strsplit / explode / strtok 不支持单词边界,因此要获得更准确的拆分,请使用带有\w的正则表达式

preg_split('/[\s]+/',$string,1);

这会将带有边界的单词拆分为 1。

【讨论】:

没有理由将\s 包装在字符类中。【参考方案14】:

如果您想知道每个函数的速度有多快,我在 PHP 7.3 中对这里投票最多的六个答案进行了一些粗略的基准测试(strpossubstrexplodecurrent、@ 987654326@、explodetrimstr_word_countstrtok) 分别进行 1,000,000 次迭代以比较它们的速度。

<?php

$strTest = 'This is a string to test fetching first word of a string methods.';

$before = microtime(true);
for ($i=0 ; $i<1000000 ; $i++) 
    $p = strpos($strTest, ' ');
    $p !== false ? $strTest : substr( $strTest, 0, $p );

$after = microtime(true);
echo 'strpos/ substr: '.($after-$before)/$i . ' seconds<br>';

$before = microtime(true);
for ($i=0 ; $i<1000000 ; $i++) 
    strstr($strTest, ' ', true);

$after = microtime(true);
echo 'strstr: '.($after-$before)/$i . ' seconds<br>';

$before = microtime(true);
for ($i=0 ; $i<1000000 ; $i++) 
    current(explode(' ',$strTest));

$after = microtime(true);
echo 'explode/ current: '.($after-$before)/$i . ' seconds<br>';

$before = microtime(true);
for ($i=0 ; $i<1000000 ; $i++) 
    $arr = explode(' ',trim($strTest));
    $arr[0];

$after = microtime(true);
echo 'explode/ trim: '.($after-$before)/$i . ' seconds<br>';

$before = microtime(true);
for ($i=0 ; $i<1000000 ; $i++) 
    str_word_count($strTest, 1);

$after = microtime(true);
echo 'str_word_count: '.($after-$before)/$i . ' seconds<br>';

$before = microtime(true);
for ($i=0 ; $i<1000000 ; $i++) 
    strtok($value, ' ');

$after = microtime(true);
echo 'strtok: '.($after-$before)/$i . ' seconds<br>';

?>

以下是 2 次连续运行的不同结果:

strpos/ substr: 6.0736894607544E-8 seconds
strstr: 5.0434112548828E-8 seconds
explode/ current: 3.5163116455078E-7 seconds
explode/ trim: 3.8683795928955E-7 seconds
str_word_count: 4.6665270328522E-6 seconds
strtok: 4.9849510192871E-7 seconds

strpos/ substr: 5.7171106338501E-8 seconds
strstr: 4.7624826431274E-8 seconds
explode/ current: 3.3753299713135E-7 seconds
explode/ trim: 4.2293286323547E-7 seconds
str_word_count: 3.7025549411774E-6 seconds
strtok: 1.2249300479889E-6 seconds

以及倒转函数顺序后的结果:

strtok: 4.2612719535828E-7 seconds
str_word_count: 4.1899878978729E-6 seconds
explode/ trim: 9.3175292015076E-7 seconds
explode/ current: 7.0811605453491E-7 seconds
strstr: 1.0137891769409E-7 seconds
strpos/ substr: 1.0082197189331E-7 seconds

结论事实证明,这些函数之间的速度差异很大,并且在测试运行之间并没有您预期的那么一致。根据这些快速而肮脏的测试,所选择的六个函数中的任何一个都可以在合理的时间内完成工作。存在干扰,包括正在运行的其他进程会干扰执行时间。因此,只需使用对您作为程序员来说最实用和最易读的任何函数。有关更大的编程图,请参阅Donald Knuth's Literate Programming

【讨论】:

如果我看到explode() 基准测试正确使用了2 的limit 参数,我会更高兴,这样就不会发生不必要的爆炸。 另外,如果要进行修整,只使用ltrim() 是合乎逻辑的。【参考方案15】:

$first_word = str_word_count(1)[0]

不适用于特殊字符,如果使用特殊字符会导致错误行为。它对 UTF-8 不友好。

更多信息请查看is PHP str_word_count() multibyte safe?

【讨论】:

【参考方案16】:

您的问题可以重新表述为“替换字符串中的第一个空格和后面的所有内容”。所以这可以通过一个简单的正则表达式来实现:

$firstWord = preg_replace("/\s.*/", '', ltrim($myvalue));

为了安全起见,我添加了对 ltrim() 的可选调用:此函数删除字符串开头的空格。

【讨论】:

以上是关于如何在 PHP 中获取句子的第一个单词?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用正则表达式仅捕获具有特定格式的有效句子的第一个单词? [复制]

如何在给定上下文的句子中获取特定标记(单词)的概率

php - 如何检查句子是不是由单个单词组成? [复制]

如何在句子列表中的单词和左括号之间创建空格

PHP PHP在完整句子中获取字符串的第一个字符

如何通过C#中的特定片段从句子中提取整个单词?