【问题标题】:Capitalize first letter of each word with exception of articles, conjunctions, and prepositions除冠词、连词和介词外,每个单词的首字母大写
【发布时间】:2012-08-08 18:40:17
【问题描述】:

我正在为使用 Codeigniter 构建的自定义 CMS 编写标签系统,并且正在尝试强制执行特定格式。

基本上,我需要将每个单词的第一个字母大写,以下除外,应该是小写:

  • 文章:a、an、the
  • 并列连词:and、but、or、for、nor 等。
  • 介词(少于五个字母):with、on、at、to、from、by 等。

此外,如果标签以上述之一开头,则应大写。

一些格式正确的标签示例:

  • 权力的游戏
  • 人鼠之间
  • 从头到尾
  • 指环王
  • 极品飞车

到目前为止,我只有:

$tag = 'Lord of the Rings';
$tag = ucwords($tag); 

$patterns = array('/A/', '/An/', '/The/', '/And/', '/Of/', '/But/', '/Or/', '/For/', '/Nor/', '/With/', '/On/', '/At/', '/To/', '/From/', '/By/' );
$lowercase = array('a', 'an', 'the', 'and', 'of', 'but', 'or', 'for', 'nor', 'with', 'on', 'at', 'to', 'from', 'by' );

$formatted_tag = preg_replace($patterns, $lowercase, $tag);

// capitalize first letter of string
$formatted_tag = ucfirst($formatted_tag);

echo $formatted_tag;

这会产生 指环王 的正确结果,但是如何避免重复数组?当我添加新单词时,将它们匹配起来很乏味。

我确定应该包含一些我缺少的单词,是否有任何现有的函数或类可以使用?

【问题讨论】:

标签: php codeigniter tags


【解决方案1】:

如果您使用带有preg_replace_callback() 的自定义回调,则不需要$lowercase 数组。此外,您当前的方法需要字边界,否则它将用android 替换Android 或用band 替换bAnd。最后,为 N 个单词创建 N 个正则表达式是低效且不必要的,因为这可以通过一个正则表达式完成。

我只保留一个单词数组:

$words = array('A', 'An', 'The', 'And', 'Of', 'But', 'Or', 'For', 'Nor', 'With', 'On', 'At', 'To', 'From', 'By' );

并创建一个动态正则表达式,完成单词边界,如下所示:

$regex = '/\b(' . implode( '|', $words) . ')\b/i';

现在将所有匹配项替换为小写对应项:

$formatted_tag = preg_replace_callback( $regex, function( $matches) {
    return strtolower( $matches[1]);
}, $tag);

【讨论】:

  • 太棒了,不知道 _callback。我注意到的一个问题是,如果有人键入指环王,“THE”会全部大写。我考虑在 ucwords() 之前将整个字符串小写,但我不想在 WoW(魔兽世界)这样的情况下丢失所有的大写字母,Wow 没有意义。如何将其更改为不区分大小写?
  • @MotiveKyle - 很简单,将 /i 修饰符添加到正则表达式:'/\b(' . implode( '|', $words) . ')\b/i'; 我将其编辑到我的答案中。
猜你喜欢
  • 2020-08-30
  • 2015-12-10
  • 2016-12-05
  • 2015-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-23
相关资源
最近更新 更多