PHP 字符串处理
字符串是 PHP 中最常见的数据类型,几乎所有的 Web 应用都需要大量的字符串处理:用户输入验证、HTML 生成、数据格式化、文本搜索替换……PHP 提供了超过 100 个字符串处理函数,覆盖了几乎所有字符串操作需求。
在处理中文等多字节字符时,必须使用 mb_ 系列函数(Multibyte String),否则普通字符串函数会按字节操作,导致中文被截断或长度计算错误。
字符串定义方式
PHP 有四种定义字符串的方式,各有适用场景:
// 1. 单引号:不解析变量,只支持 \\ 和 \' 转义 $str1 = '这是单引号字符串,$name 不会被解析';`// 2. 双引号:解析变量和转义字符 $name = "张三"; $str2 = "你好,$name!\n"; // 解析变量和换行符 $str3 = "你好,{$name}的朋友!"; // 花括号语法,更清晰
// 3. Heredoc:多行字符串,解析变量 $html = <<<EOT <div class="user"> <h2>$name</h2> <p>欢迎回来</p> </div> EOT;
// 4. Nowdoc:多行字符串,不解析变量(类似单引号) $template = <<<'EOT' 变量 $name 在这里不会被解析 这适合存储代码模板 EOT; ``
长度与大小写
php $str = "Hello, World!"; $cn = "你好,世界!";`// 长度 echo strlen($str); // 13(字节数) echo mb_strlen($str); // 13(字符数) echo strlen($cn); // 18(UTF-8 中每个中文占3字节) echo mb_strlen($cn); // 6(字符数,正确)
// 大小写转换 echo strtoupper($str); // HELLO, WORLD! echo strtolower($str); // hello, world! echo ucfirst("hello world"); // Hello world(首字母大写) echo ucwords("hello world"); // Hello World(每词首字母大写) echo mb_strtoupper("hello"); // HELLO(支持多字节)
`查找与判断
php $str = "PHP 是世界上最好的语言,PHP 很流行";`// 查找位置(返回索引,找不到返回 false) echo strpos($str, "PHP"); // 0(第一次出现的位置) echo strrpos($str, "PHP"); // 14(最后一次出现) echo strpos($str, "Python"); // false
// PHP 8+ 更语义化的判断函数 var_dump(str_contains($str, "最好")); // true var_dump(str_starts_with($str, "PHP")); // true var_dump(str_ends_with($str, "流行")); // true
// 注意:strpos 返回 false 时要用 === 判断 if (strpos($str, "PHP") !== false) { echo "找到了"; } // 不能用 if (strpos($str, "PHP")) 因为位置0也是假值!
`替换
php $str = "PHP 是世界上最好的语言,PHP 很流行";`// 基本替换(区分大小写) echo str_replace("PHP", "Python", $str); // Python 是世界上最好的语言,Python 很流行
// 不区分大小写替换 echo str_ireplace("php", "Go", $str);
// 多对多替换 echo str_replace( ["PHP", "语言", "流行"], ["Python", "编程语言", "受欢迎"], $str );
// 正则替换 echo preg_replace('/PHP/i', 'Go', $str); // 不区分大小写 echo preg_replace('/\d+/', 'N', "PHP 8 发布于 2020 年"); // PHP N 发布于 N 年
`截取与分割
php $str = "Hello, World!";`// 截取子字符串 echo substr($str, 7); // World!(从位置7到末尾) echo substr($str, 7, 5); // World(从位置7取5个字符) echo substr($str, -6); // orld!(从末尾倒数6个) echo mb_substr("你好世界", 1, 2); // 好世(中文截取)
// 分割字符串 $csv = "苹果,香蕉,橙子,葡萄"; $arr = explode(",", $csv); // ["苹果","香蕉","橙子","葡萄"] $arr = explode(",", $csv, 3); // ["苹果","香蕉","橙子,葡萄"](最多3段)
// 合并数组为字符串 echo implode(" | ", $arr); // 苹果 | 香蕉 | 橙子,葡萄 echo join(", ", ["a", "b", "c"]); // a, b, c(join 是 implode 的别名)
// 按字符分割 $chars = str_split("Hello", 2); // ["He","ll","o"]
`清理与格式化
php // 去除空白 $str = " Hello World "; echo trim($str); // "Hello World"(两端) echo ltrim($str); // "Hello World "(左端) echo rtrim($str); // " Hello World"(右端) echo trim($str, "Hd"); // "ello Worl"(去除指定字符)`// 填充 echo str_pad("5", 3, "0", STR_PAD_LEFT); // 005(左填充) echo str_pad("Hi", 10, "-", STR_PAD_BOTH); // ----Hi----(两端填充)
// 重复 echo str_repeat("=-", 5); // =-=-=-=-=-=-
// 格式化数字 echo number_format(1234567.891, 2, '.', ','); // 1,234,567.89 echo sprintf("%.2f", 3.14159); // 3.14 echo sprintf("%05d", 42); // 00042 echo sprintf("%-10s|", "left"); // "left |"(左对齐)
// 字符串反转 echo strrev("Hello"); // olleH
// 单词数量 echo str_word_count("Hello World PHP"); // 3
`正则表达式
正则表达式是处理复杂字符串模式的强大工具:
php // preg_match:匹配一次,返回 0 或 1 $email = "user@example.com"; if (preg_match('/^[\w.+-]+@[\w-]+\.[a-z]{2,}$/i', $email)) { echo "邮箱格式正确"; }`// preg_match_all:匹配所有,返回匹配数量 $html = '<a href="https://php.net">PHP</a> <a href="https://mysql.com">MySQL</a>'; $count = preg_match_all('/href="([^"]+)"/', $html, $matches); echo $count; // 2 print_r($matches[1]); // ["https://php.net", "https://mysql.com"]
// preg_replace:正则替换 $str = "2024-01-15"; echo preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3/$2/$1', $str); // 15/01/2024
// preg_split:正则分割 $str = "one1two2three3four"; $parts = preg_split('/\d/', $str); // ["one", "two", "three", "four"]
mb_中文字符串处理
处理中文必须使用
系列函数,并确保编码一致:`php // 设置内部编码(建议在入口文件设置) mb_internal_encoding("UTF-8");$str = "你好,世界!PHP 教程";
echo mb_strlen($str); // 11(字符数) echo mb_substr($str, 0, 5); // 你好,世界 echo mb_strpos($str, "PHP"); // 6 echo mb_strtoupper("hello"); // HELLO echo mb_convert_encoding($str, "GBK", "UTF-8"); // 转换编码
// 中文字符串截取(带省略号) function mbSubstr(string $str, int $len, string $suffix = '...'): string { if (mb_strlen($str) <= $len) return $str; return mb_substr($str, 0, $len) . $suffix; } echo mbSubstr("这是一段很长的中文标题文字", 8); // 这是一段很长的中文...
常见问题
Q:strlen 和 mb_strlen 有什么区别? A:strlen 返回字节数,mb_strlen 返回字符数。对于纯 ASCII 字符串两者相同;对于 UTF-8 中文,每个汉字占 3 字节,strlen("你好") 返回 6,而 mb_strlen("你好") 返回 2。处理中文时必须用 mb_ 系列函数。
Q:如何防止 XSS 攻击中的字符串注入? A:将用户输入输出到 HTML 时,使用 htmlspecialchars($str, ENT_QUOTES, 'UTF-8') 转义特殊字符,将 <、>、"、'、& 转换为 HTML 实体,防止恶意脚本注入。
Q:正则表达式中 preg_match 和 strpos 哪个更快? A:对于简单的字符串查找,strpos 比正则快得多。只有在需要复杂模式匹配时才使用正则。PHP 8 的 str_contains、str_starts_with、str_ends_with 比正则更快更语义化。
Q:如何安全地截断 HTML 字符串? A:直接截断 HTML 字符串可能破坏标签结构。可以先用 strip_tags()` 去除 HTML 标签再截断,或使用专门的 HTML 截断库。