【问题标题】:In paragraph making the first letter of every sentence uppercase?在段落中使每个句子的第一个字母大写?
【发布时间】:2018-03-06 01:00:33
【问题描述】:

我从 php.net 获得了这个函数,用于将句子中的大写转换为小写。

function sentence_case($string) {
    $sentences = preg_split('/([.?!]+)/', $string, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
    $new_string = '';
    foreach ($sentences as $key => $sentence) {
        $new_string .= ($key & 1) == 0
            ? ucfirst(strtolower(trim($sentence)))
            : $sentence . ' ';
    }
    return trim($new_string);
}

如果句子不在段落中,一切正常。但如果句子在段落中,则开头段落中的第一个字母 (<p>) 或中断 (<br>) 标签 HTML 变为小写。

这是示例:

之前:

<p>Lorem IPSUM is simply dummy text. LOREM ipsum is simply dummy text! wHAt is LOREM IPSUM? Hello lorem ipSUM!</p>

输出:

<p>lorem ipsum is simply dummy text. Lorem ipsum is simply dummy text! What is lorem ipsum? Hello lorem ipsum!</p>

谁能帮我把段落中的第一个字母变成大写字母?

【问题讨论】:

    标签: php html domparser ucfirst sentencecase


    【解决方案1】:

    在解析有效的 html 时,最好使用合法的 DOM 解析器。使用正则表达式并不可靠,因为正则表达式不知道标记和类似于标记的子字符串之间的区别。

    代码:(Demo)

    $html = <<<HTML
    <p>Lorem IPSUM is simply dummy text.<br>Here is dummy text. LOREM ipsum is simply dummy text! wHAt is LOREM IPSUM? Hello lorem ipSUM!</p>
    HTML;
    
    libxml_use_internal_errors(true);
    $dom = new DOMDocument();
    $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    $xpath = new DOMXPath($dom);
    foreach($xpath->query('//text()') as $textNode) {
        $textNode->nodeValue = preg_replace_callback(
            '/(?:^|[.!?]) *\K[a-z]+/',
            function($m) {
                return ucfirst($m[0]);
            },
            strtolower($textNode->nodeValue)
        );
    }
    echo $dom->saveHTML();
    

    输出:

    <p>Lorem ipsum is simply dummy text.<br>Here is dummy text. Lorem ipsum is simply dummy text! What is lorem ipsum? Hello lorem ipsum!</p>
    

    上面的sn-p没有:

    1. 允许首字母缩写词全部大写(因为 OP 希望在将选定字母变为大写之前将所有字母转换为小写)
    2. 懒得正确处理多字节字符(因为 OP 没有表明这种必要性)
    3. 不知道句中点和句尾点之间的区别(由于英语标点符号的歧义)

    【讨论】:

      【解决方案2】:

      试试这个

      function html_ucfirst($s) {
      return preg_replace_callback('#^((<(.+?)>)*)(.*?)$#', function ($c) {
              return $c[1].ucfirst(array_pop($c));
       }, $s);
      }
      

      并调用此函数

      $string= "<p>Lorem IPSUM is simply dummy text. LOREM ipsum is simply dummy text! wHAt is LOREM IPSUM? Hello lorem ipSUM!</p>";
      echo html_ucfirst($string);
      

      这里是工作演示:https://ideone.com/fNq3Vo

      【讨论】:

        【解决方案3】:

        您的问题是您在句子中考虑 HTML,因此句子的第一个“单词”是 &lt;P&gt;lorem,而不是 Lorem

        您可以将正则表达式更改为 /([&gt;.?!]+)/,但这样您会在“Lorem”之前看到 额外的空格,因为系统现在看到 两个 句子而不是一个。

        另外,现在Hello &lt;em&gt;there&lt;/em&gt; 将被视为四个句。

        这看起来很像“如何使用正则表达式来解释 (X)HTML”?

        【讨论】:

          【解决方案4】:

          你可以用 CSS 轻松做到这一点

          p::first-letter {
              text-transform: uppercase;
          }
          

          【讨论】:

          • 我知道我可以使用“p:first-letter”,但我不想要,因为搜索引擎(谷歌机器人)仍然使用小写字母。我认为这对 SEO 不利。谢谢。
          • 据我所知,SEO 不关心大小写。它只关注其中的内容
          猜你喜欢
          • 2013-08-13
          • 1970-01-01
          • 2022-11-27
          • 1970-01-01
          • 2014-05-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-04
          相关资源
          最近更新 更多