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

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

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

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

【问题讨论】:

标签: php string extract text-segmentation


【解决方案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() 的可选调用:此函数删除字符串开头的空格。

      【讨论】:

        猜你喜欢
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多