1

我将所有单词大写,然后将a 、 of 和单词小写。第一个词和最后一个词应保持大写。我尝试使用而不是 \b,这导致了一些奇怪的问题。我也尝试过,但这似乎并不意味着“不是字符串结尾”\s[^$]

function titleize($string){
  return ucfirst(
     preg_replace("/\b(A|Of|An|At|The|With|In|To|And|But|Is|For)\b/uie",
     "strtolower('$1')", 
     ucwords($string))
  );
}

这是我试图修复的唯一失败的测试。最后的“in”应保持大写。

titleize("gotta give up, gotta give in");
//Gotta Give Up, Gotta Give In

这些测试通过:

titleize('if i told you this was killing me, would you stop?');
//If I Told You This Was Killing Me, Would You Stop?

titleize("we're at the top of the world (to the simple two)");
//We're at the Top of the World (to the Simple Two)

titleize("and keep reaching for those stars");
//And Keep Reaching for Those Stars
4

3 回答 3

1

ucwords()在将字符串发送到 regex-replace 之前申请,然后ucfirst在从 regex 返回后再次申请(对于出现在字符串开头的单词)。这可以通过以下约定来缩短:字符串开头和结尾的每个单词都没有被空格包围。使用这个约定,我们可以使用像'/(?<=\s)( ... )(?=\s)/'. 这将以某种方式简化您的功能:

function titleize2($str) {
 $NoUc = Array('A','Of','An','At','The','With','In','To','And','But','Is','For');
 $reg = '/(?<=\s)('      # set lowercase only if surrounded by whitespace
      . join('|', $NoUc) # add OR'ed list of words
      . ')(?=\s)/e';     # set regex-eval mode
 return preg_replace( $reg, 'strtolower("\\1")', ucwords($str) );
}

如果测试:

...
$Strings = Array('gotta give up, gotta give in',
                 'if i told you this was killing me, would you stop?',
                 'we\'re at the top of the world (to the simple two)',
                 'and keep reaching for those stars');

foreach ($Strings as $s)
   print titleize2($s) . "\n";
...

...这将返回正确的结果。

于 2012-07-22T14:36:02.653 回答
0

试试这个正则表达式:

/\b(A|Of|An|At|The|With|In|To|And|But|Is|For)(?!$)\b/uie

负前瞻(?!$)排除了 endofline 之后的匹配项。

于 2012-07-22T11:31:57.820 回答
0

为行尾添加负前瞻(?!$)应该可以满足您的要求

function titleize($string){
  return ucfirst(
     preg_replace("/\b(A|Of|An|At|The|With|In|To|And|But|Is|For)\b(?!$)/uie",
     "strtolower('$1')", 
     ucwords(inflector::humanize($string)))
  );
}
于 2012-07-22T11:32:17.833 回答