我正在尝试创建一个简单的脚本,从PHP文件/字符串中删除所有不必要的空格。
我已成功使用标记解析字符串,但没有看到删除“额外”空格的好方法。
例如,
function test() { return TRUE; }
应该是
function test(){return TRUE;}
而不是
functiontest(){returnTRUE;}
如果只删除T_WHITESPACE标记,则最终会得到最后一个版本。
我是否缺少删除空格的内容,但在“函数”和“返回”之类的内容后保留空格。谢谢!
答案 0 :(得分:3)
$newSource = '';
foreach (token_get_all($source) as $i => $token) {
if (!is_array($token)) {
$newSource .= $token;
}
if ($token[0] == T_WHITESPACE) {
if ( isset($tokens[$i - 1]) && isset($tokens[$i + 1])
&& is_array($tokens[$i - 1]) && is_array($tokens[$i + 1])
&& isLabel($tokens[$i - 1][1]) && isLabel($tokens[$i + 1][1])
) {
$newSource .= ' ';
}
} else {
$newSource .= $token[1];
}
}
function isLabel($str) {
return preg_match('~^[a-zA-Z0-9_\x7f-\xff]+$~', $str);
}
除了在其两侧都有LABEL
的情况之外,总是允许删除空格。我检查一下,并且不添加任何内容或单个空格字符。
我知道另一个特殊情况,空白很重要:T_END_HEREDOC
必须跟;
或\n
。不允许在这里压缩或剥离空间。所以,如果这对你很重要,你可以简单地添加;)
答案 1 :(得分:1)
好吧,T_WHITESPACE
可以是空格或换行符等等。因此,一个简单的方法是自动将所有T_WHITESPACE
个实例替换为一个只包含一个空格的新实例。
但是对于一个更聪明的方法,只需浏览list of parser tokens,然后找出哪些应该有一个空格,哪些不应该(像这样):
foreach ($tokens as $k => $val) {
if (is_array($val) && $val[0] == T_WHITESPACE) {
if (!is_array($tokens[$k - 1])) {
//remove this space
} else {
switch ($tokens[$k - 1][0]) {
case T_ABSTRACT:
case T_FUNCTION:
//.. other keeps here:
continue;
break;
default:
//remove the space
}
}
}
}
还有一点需要注意,不要为了表现而这样做。如果您使用的是OPCODE缓存(例如APC),那么您将看到很多工作没有任何好处。如果你没有使用它,为什么不是你?
答案 2 :(得分:1)
你的努力是徒劳的。
php -w
允许已经从脚本中删除空格。它使用更复杂的逻辑来从令牌流中删除空格
以下是zend_strip()
中的zend_highlight.c
函数:
while ((token_type=lex_scan(&token TSRMLS_CC))) {
switch (token_type) {
case T_WHITESPACE:
if (!prev_space) {
zend_write(" ", sizeof(" ") - 1);
prev_space = 1;
}
/* lack of break; is intentional */
case T_COMMENT:
case T_DOC_COMMENT:
token.type = 0;
continue;
case T_END_HEREDOC:
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
efree(token.value.str.val);
/* read the following character, either newline or ; */
if (lex_scan(&token TSRMLS_CC) != T_WHITESPACE) {
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
}
zend_write("\n", sizeof("\n") - 1);
prev_space = 1;
token.type = 0;
continue;
default:
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
break;
}
if (token.type == IS_STRING) {
switch (token_type) {
case T_OPEN_TAG:
case T_OPEN_TAG_WITH_ECHO:
case T_CLOSE_TAG:
case T_WHITESPACE:
case T_COMMENT:
case T_DOC_COMMENT:
break;
default:
efree(token.value.str.val);
break;
}
}
prev_space = token.type = 0;
}