本问题已经有最佳答案,请猛点这里访问。
示例:我有一个$variable ="_foo",我想绝对确保$variable不以下划线"_"开头。如何在PHP中做到这一点?是否可以访问字符串后面的char数组?
有人发布了一个使用正则表达式的答案,令人惊讶地被否决了4次,理由是它"不适合使用正则表达式"。由于同龄人的压力,该答案的所有者删除了它。如果输入验证不能很好地使用正则表达式,我不知道它是什么。在这个用例中,性能不是一个重要的因素。如果海报想取消删除正则表达式的答案,我会很高兴地投赞成票。
@asaph:正则表达式使用过度,建议过多。对于这个用例,它们完全是杀戮过度。我不明白你怎么能声称绩效不是一个重要因素;你当然不会支持它。
恐怕我同意@lightnessracesinorbit的说法,对于不懂PHP基础知识的人来说,regex是一个过分的、人为的答案。我想瑞格回答者刚刚说,"哎呀!":)
@Henrikerlandson Regex和非Regex解决方案都是有效的;任何性能问题都应作为警告添加到正文中或在评论中指出。OP并不是唯一一个从他们的问题中受益的人;读者可以决定采用哪种解决方案。
@Rath任何没有副作用或直接错误的过于复杂的答案都是有效的,并不意味着这是一个好的答案。尤其是因为OP还询问了char数组。
@亨利克兰森,你说得对。干杯
$variable[0] !="_"
它是如何工作的?
在PHP中,可以使用数组索引表示法获取字符串的特定字符。$variable[0]是字符串的第一个字符(如果$variable是字符串)。
解释一下为什么这样做会很好,但是无论如何+1。
你走吧。为您添加了解释。
在访问第一个字节之前,应该测试字符串是否至少有一个字节长。
跳过php 5.3.0上对我有效的测试
令人惊讶的是,人们在想到这个之前会想到SUBSTR和STRPOS……
令人惊讶的是,人们会要求解释而不是查阅手册。
@访问不存在的字节会导致未初始化的字符串偏移通知。
这适用于单个字符,但我认为substr是一个更通用的解决方案,可以适用于多个字符,而且我认为regex太远了。也不是说我没想到这个…它正在编程101。
很久以前,python就已经有了这种访问子字符串的语法。
@杜索夫:不幸的是,这并不少见。
对于请求的单字符大小写:$starts_with_underline=(is_string($variable)&;$variable!='&;&;$variable[0]==''')将检查其a字符串,并且在访问元素0之前存在字符。如果你能保证你首先知道它是一个字符串,你就可以放弃第一个测试。
天才今天教我一些新东西的赞成票:)
是什么意思?!为什么这不是更常见的知识?我旁边的开发人员也从未听说过这个。
您可以在PHP中签出substr函数,然后以这种方式获取第一个字符:
http://php.net/manual/en/function.substr.php
if (substr('_abcdef', 0, 1) === '_') { ... }
由于有人提到效率,我对迄今为止给出的函数进行了基准测试,出于好奇:
function startsWith1($str, $char) {
return strpos($str, $char) === 0;
}
function startsWith2($str, $char) {
return stripos($str, $char) === 0;
}
function startsWith3($str, $char) {
return substr($str, 0, 1) === $char;
}
function startsWith4($str, $char){
return $str[0] === $char;
}
function startsWith5($str, $char){
return (bool) preg_match('/^' . $char . '/', $str);
}
function startsWith6($str, $char) {
if (is_null($encoding)) $encoding = mb_internal_encoding();
return mb_substr($str, 0, mb_strlen($char, $encoding), $encoding) === $char;
}
以下是我的平均Dualcore机器的结果,每台机器运行10万次。
// Testing '_string'
startsWith1 took 0.385906934738
startsWith2 took 0.457293987274
startsWith3 took 0.412894964218
startsWith4 took 0.366240024567
startsWith5 took 0.642996072769
startsWith6 took 1.39859509468
// Tested"string"
startsWith1 took 0.384965896606
startsWith2 took 0.445554971695
startsWith3 took 0.42377281189
startsWith4 took 0.373164176941
startsWith5 took 0.630424022675
startsWith6 took 1.40699005127
// Tested 1000 char random string [a-z0-9]
startsWith1 took 0.430691003799
startsWith2 took 4.447286129
startsWith3 took 0.413349866867
startsWith4 took 0.368592977524
startsWith5 took 0.627470016479
startsWith6 took 1.40957403183
// Tested 1000 char random string [a-z0-9] with '_' prefix
startsWith1 took 0.384054899216
startsWith2 took 4.41522812843
startsWith3 took 0.408898115158
startsWith4 took 0.363884925842
startsWith5 took 0.638479948044
startsWith6 took 1.41304707527
如您所见,将haystack作为数组来查找第一个位置的char始终是最快的解决方案。它也总是以相同的速度执行,不管字符串的长度如何。对于短字符串,使用strpos比substr快,而对于长字符串,当字符串不以前缀开头时,使用strpos比使用substr慢。不过,两者之间的差别无关紧要。stripos的速度非常慢,带有长字符串。无论字符串长度如何,preg_match的性能基本相同,但速度一般。mb_substr解决方案的性能最差,但可能更可靠。
考虑到这些数字适用于100000次跑步,很明显我们谈论的是每次通话0.0000x秒。为了效率而选择一个又一个是毫无价值的微观优化,除非你的应用在做startsWith的生活检查。
+1:坦率地说,我真的很惊讶preg_match这么快。
我喜欢性能测试和结果。+ 1。
这是最简单的答案,您不关心性能:
if (strpos($string, '_') === 0) {
# code}
如果strpos返回0,则表示您要查找的内容从字符串的开头字符0开始。
本文详细记录如下:http://uk3.php.net/manual/en/function.strpos.php
(PS $string[0] === '_'是最好的答案)
function starts_with($s, $prefix){
// returns a bool
return strpos($s, $prefix) === 0;
}
starts_with($variable,"_");
+1所有其他解决方案都会在空字符串输入上出错。
效率低下-如果没有立即找到前缀,则扫描整个字符串。
从substr手册:"如果字符串长度小于或等于起始字符,则返回FALSE。"因此SUBSTR($foo,0,1)与空字符串完美配合。
正如塞瓦所说,这实在是太低效了。如果必须使用函数,我将使用SUBSTR而不是strpos
@维姆:谢谢你指出这一点。PHP的另一个例子是,它具有一种非指导性的、但很方便的行为。
if($s==="") return false; else use_other_solution();这意味着其他解决方案也可以成为空字符串证明。
这里有一个更好的开始功能:
function mb_startsWith($str, $prefix, $encoding=null) {
if (is_null($encoding)) $encoding = mb_internal_encoding();
return mb_substr($str, 0, mb_strlen($prefix, $encoding), $encoding) === $prefix;
}
这项工程解决了什么问题?
他在检查下划线,而不是重音。
@只有某人:它允许在考虑多字节字符串的同时测试任意前缀。
以松林格拉的回答为基础,并回应Gumbo对该回答的评论:
function has_leading_underscore($string) {
return $string[0] === '_';
}
在php 5.3.0上运行时,即使不检查字符串的长度是否至少为1个字符,也可以使用以下命令并返回预期值:
echo has_leading_underscore('_somestring').', ';
echo has_leading_underscore('somestring').', ';
echo has_leading_underscore('').', ';
echo has_leading_underscore(null).', ';
echo has_leading_underscore(false).', ';
echo has_leading_underscore(0).', ';
echo has_leading_underscore(array('_foo', 'bar'));
/*
* output: true, false, false, false, false, false, false
*/
我不知道其他版本的PHP会做出什么反应,但是如果它们都能工作,那么这个方法可能比子路由更有效。
为什么使用字符串"是"/"否"?这门语言有许多优点。
@查德,我不记得了。如果我不得不猜测,那可能是因为我直接打印了结果,出于某种原因,我想读"是/否"而不是"真/假"。您是对的,使用布尔值会更好,而且它还可以简化逻辑。我会改变的。