【发布时间】:2011-02-18 09:11:36
【问题描述】:
我也有带有变音符号的 UTF-8 文本,并且想检查该文本的第一个字母是大写还是小写。如何做到这一点?
【问题讨论】:
-
为什么要检查一个字母是大写还是小写?
-
@Elizabeth Buckwalter 因为我从这个文本中计算出其他文本,如果第一个字母高于我必须对第二个字母做同样的事情。
我也有带有变音符号的 UTF-8 文本,并且想检查该文本的第一个字母是大写还是小写。如何做到这一点?
【问题讨论】:
function starts_with_upper($str) {
$chr = mb_substr ($str, 0, 1, "UTF-8");
return mb_strtolower($chr, "UTF-8") != $chr;
}
请注意,mb_substr 是正确隔离第一个字符所必需的。
【讨论】:
使用ctype_upper检查大写:
$a = array("Word", "word", "wOrd");
foreach($a as $w)
{
if(ctype_upper($w{0}))
{
print $w;
}
}
【讨论】:
ctype_upper 不适用于 非 ASCII 字符(包括那些北欧拉丁文,以及许多其他拉丁文,尤其是非拉丁文字符)。
0 字节偏移量获取多字节字符——您只能访问该字母的第一个字节。 2.ctype_没有为此任务提供必要的多字节支持。
我认为,与此处发布的其他解决方案相比,拨打preg_ 是最直接、最简洁、最可靠的呼叫。
echo preg_match('~^\p{Lu}~u', $string) ? 'upper' : 'lower';
我的模式分解:
~ # starting pattern delimiter
^ #match from the start of the input string
\p{Lu} #match exactly one uppercase letter (unicode safe)
~ #ending pattern delimiter
u #enable unicode matching
当ctype_ 和< 'a' 在这一系列测试中失败时请注意。
代码:(Demo)
$tests = ['âa', 'Bbbbb', 'Éé', 'iou', 'Δδ'];
foreach ($tests as $test) {
echo "\n{$test}:";
echo "\n\tPREG: " , preg_match('~^\p{Lu}~u', $test) ? 'upper' : 'lower';
echo "\n\tCTYPE: " , ctype_upper(mb_substr($test, 0, 1)) ? 'upper' : 'lower';
echo "\n\t< a: " , mb_substr($test, 0, 1) < 'a' ? 'upper' : 'lower';
$chr = mb_substr ($test, 0, 1, "UTF-8");
echo "\n\tMB: " , mb_strtoupper($chr, "UTF-8") == $chr ? 'upper' : 'lower';
}
输出:
âa:
PREG: lower
CTYPE: lower
< a: lower
MB: lower
Bbbbb:
PREG: upper
CTYPE: upper
< a: upper
MB: upper
Éé: <-- trouble
PREG: upper
CTYPE: lower <-- uh oh
< a: lower <-- uh oh
MB: upper
iou:
PREG: lower
CTYPE: lower
< a: lower
MB: lower
Δδ: <-- extended beyond question scope
PREG: upper <-- still holding up
CTYPE: lower
< a: lower
MB: upper <-- still holding up
如果有人需要区分大写字母、小写字母和非字母,请参阅this post。
这可能将这个问题的范围扩展得太远,但是如果您的输入字符特别松散(它们可能不存在于Lu 可以处理的类别中),您可能需要检查第一个字符是否有大小写变种:
\p{L&} 或 \p{Cased_Letter}:以小写和大写变体形式存在的字母(Ll、Lu 和 Lt 的组合)。
若要在SMALL 变体中包含罗马数字(“数字字母”),您可以在必要时将该额外范围添加到模式中。
https://www.fileformat.info/info/unicode/category/Nl/list.htm
代码:(Demo)
echo preg_match('~^[\p{Lu}\x{2160}-\x{216F}]~u', $test) ? 'upper' : 'not upper';
【讨论】:
试过了吗?
$str = 'the text to test';
if($str{0} === strtoupper($str{0})) {
echo 'yepp, its uppercase';
}
else{
echo 'nope, its not upper case';
}
【讨论】:
0 字节偏移量获取多字节字符——您只能访问该字母的第一个字节。 2.strtoupper没有为此任务提供必要的多字节支持。
在 Kohana 2 自动加载功能中使用:
echo $char < 'a' ? 'uppercase' : 'lowercase';
当一个字符串字符被转换为整数时,它会计算为它的 ASCII 数字。如您所知,在 ASCII 表中首先有一些控制字符和其他字符。然后是拉丁字母的大写字母。然后是拉丁字母中的小写字母。因此,您可以轻松检查一个字母的代码是小于还是大于拉丁小字符a。
顺便说一句,这比使用正则表达式的解决方案快两倍左右。
【讨论】:
请注意,PHP 提供了 ctype 系列,如 ctype_upper。
您必须首先通过setLocale() 正确设置语言环境,才能使其与UTF-8 一起使用。
例如,请参阅ctype_alpha 上的评论。
用法:
if ( ctype_upper( $str[0] )) {
// deal with 1st char of $str is uppercase
}
【讨论】:
setlocale(LC_ALL, 'ru_RU.utf-8'); return ctype_upper('П') === false;
setLocale() 设置正确可能很麻烦。更重要的是,您不能通过第一个字节偏移量访问整个多字节字符。这个答案不正确/不稳定。 3v4l.org/38R6f
我不想让数字和其他人成为大字符,所以我使用:
if(preg_match('/[A-Z]$/',$char)==true)
{
// this must be an upper char
echo $char
}
【讨论】:
刚刚呢:
if (ucfirst($string) == $string) {dosomething();}
【讨论】:
如果你想要一个好的功能,我用过这个:
function _is_upper ($in_string)
{
return($in_string === strtoupper($in_string) ? true : false);
}
那就打电话吧..
if (_is_upper($mystring))
{
// Do....
}
【讨论】:
PHP 7 中另一个可能的解决方案是使用IntlChar
IntlChar 提供对许多实用方法的访问,这些方法可用于访问有关 Unicode 字符的信息。
$tests = ['âa', 'Bbbbb', 'Éé', 'iou', 'Δδ'];
foreach ($tests as $test) {
echo "{$test}:\t";
echo IntlChar::isUUppercase(mb_substr($test, 0, 1)) ? 'upper' : 'lower';
echo PHP_EOL;
}
输出:
âa: lower
Bbbbb: upper
Éé: upper
iou: lower
Δδ: upper
虽然@mickmackusa 的第一个模式(~^\p{Lu}~u)很好,但对于不同的一般类别值(“Lu”大写字母类别除外),它会给出错误的结果。 *注意,他已经将答案底部的模式扩展到包括罗马数字。
例如
var_dump(preg_match('~^\p{Lu}~u', 'Ⅷ') ? 'upper' : 'lower'); // Resutl: lower
var_dump(preg_match('~^\p{Lu}~u', 'ⅷ') ? 'upper' : 'lower'); // Result: lower
但是
var_dump(IntlChar::isUUppercase(mb_substr('Ⅷ', 0, 1)) ? 'upper' : 'lower'); // Result: upper
var_dump(IntlChar::isUUppercase(mb_substr('ⅷ', 0, 1)) ? 'upper' : 'lower'); // Result: lower
如果要检查也是大写但具有不同一般类别值的字符,请确保使用IntlChar::isUUppercase 而不是IntlChar::isupper
注意:这个库依赖于intl(国际化扩展)
【讨论】:
mb_ 函数而不是依赖于库的类方法?好吧,你的选择。当它提供最直接的方法并且不会丢失合理的性能时,我总是喜欢正则表达式。为研究人员提供选择是件好事。
if(ctype_upper(&value)){
echo 'uppercase';
}
else {
echo 'not upper case';
}
【讨论】:
ctype_ 没有为此任务提供必要的多字节支持。 OP 非常清楚需要处理“变音符号”。此仅代码答案不正确/不适当。