PHP 5+ 內建 php_strip_whitespace() 可一鍵移除註釋與空白,但理解其底層原理有助於構建代碼分析、混淆、壓縮工具。本文解析基於 token_get_all() 的手寫實現,展示詞法掃描如何精準過濾 T_COMMENT、T_DOC_COMMENT、T_WHITESPACE 等 Token。
正則難以處理巢狀結構、Heredoc/Nowdoc、字符串內的類註釋字符。PHP 詞法分析器已將代碼拆解為結構化 Token 陣列,逐 Token 處理才是正統做法。
/**
* 移除代碼中的空白與註釋
* @param string $content PHP 源代碼
* @return string 處理後代碼
*/
function strip_whitespace($content) {
$stripStr = '';
$tokens = token_get_all($content);
$last_space = false;
for ($i = 0, $j = count($tokens); $i < $j; $i++) {
if (is_string($tokens[$i])) {
// 單字符 Token(如 ; { } = 等)直接保留
$last_space = false;
$stripStr .= $tokens[$i];
} else {
// 陣列 Token:[Token ID, Token 內容, 行號]
list($id, $text) = $tokens[$i];
switch ($id) {
case T_COMMENT: // // 註釋
case T_DOC_COMMENT: // /** 文檔註釋 */
// 直接丟棄
break;
case T_WHITESPACE: // 空白、換行、Tab
if (!$last_space) {
$stripStr .= ' '; // 壓縮連續空白為單空格
$last_space = true;
}
break;
case T_START_HEREDOC: // <<< 开始
$stripStr .= "<<
| 常數 | 代表 | 範例 |
|---|---|---|
| T_COMMENT | 單行/多行註釋 | // 註釋、/* 註釋 */ |
| T_DOC_COMMENT | PHPDoc 註釋 | /** 文檔 */ |
| T_WHITESPACE | 空白字符 | 空格、\t、\n、\r |
| T_START_HEREDOC | Heredoc 開始 | <<<EOF |
| T_END_HEREDOC | Heredoc 結束 | EOF; |
| T_INLINE_HTML | PHP 標籤外內容 | HTML 文本 |
<?php
$code = '<?php
// 單行註釋
/** 文檔註釋 */
$var = "hello"; /* 行尾註釋 */
$arr = [1, 2, 3];
?>';
echo strip_whitespace($code);
// 輸出:
token_get_all() 在 PHP 8+ 對屬性語法 #[Attr] 支援完善,舊版本可能誤判。echo"a""b"; 這類語法錯誤。T_WHITESPACE 替換為 \n 而非空格。掌握 Token 流處理,即掌握了 PHP 代碼結構化操作的鑰匙,是構建開發工具鏈的核心技能。