Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用解析器标记删除PHP中允许的空白_Php_Whitespace_Minify_Token - Fatal编程技术网

使用解析器标记删除PHP中允许的空白

使用解析器标记删除PHP中允许的空白,php,whitespace,minify,token,Php,Whitespace,Minify,Token,我试图制作一个简单的脚本,从PHP文件/字符串中删除所有不必要的空白 我已经成功地使用标记解析了字符串,但是没有找到一个删除“额外”空白的好方法 比如说, function test() { return TRUE; } 应该是 function test(){return TRUE;} 而不是 functiontest(){returnTRUE;} 如果只删除T_空白标记,则最终会得到最后一个版本 我是否缺少删除空格,但在“function”和“return”之后保留空格的功能。谢谢大家

我试图制作一个简单的脚本,从PHP文件/字符串中删除所有不必要的空白

我已经成功地使用标记解析了字符串,但是没有找到一个删除“额外”空白的好方法

比如说,

function test() { return TRUE; }
应该是

function test(){return TRUE;}
而不是

functiontest(){returnTRUE;}
如果只删除T_空白标记,则最终会得到最后一个版本


我是否缺少删除空格,但在“function”和“return”之后保留空格的功能。谢谢大家!

嗯,
T_空格
可以是空格或换行符等。因此,一个简单的方法是自动将所有
T_空格
实例替换为一个新实例,该实例正好由一个空格组成

但是对于一个更智能的方法,只需遍历,并找出哪些应该在后面有空格,哪些不应该(类似于下面的内容):

还有一点要注意,不要为了表现而这样做。如果您使用的是操作码缓存(如APC),那么大量工作将不会带来任何好处。如果你不使用,为什么不使用

$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);
}
除了两边都有
标签的情况外,始终允许删除空白。我检查它,要么不添加任何内容,要么添加一个空格字符

我知道还有一个特例,空白很重要:
T_END_herdoc
后面必须跟
\n
。不允许压缩或剥离此处的空间。因此,如果这对您很重要,您可以简单地添加它;)

你的努力是徒劳的

php -w
允许已删除脚本中的空白。它使用更复杂的逻辑从令牌流中删除空白。
下面是
zend_highlight.c
中的
zend_strip()
函数:

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;
}

谢谢你。这是我想我可能不得不做的方法,有点痛苦!我已经有了单空格选项,但它有点像半个空格。@Matt:我真的不得不问,你为什么要这样做?目标是什么?目标的理由是什么?基本上是一个学术练习。我经常在随机的地方重复使用我的方法,有时候如果它们只占用一行就好了。我意识到这对速度/执行没有真正的影响。@Matt:好吧,很公平。仍然不是一个好主意(复制粘贴等)。最好使用库并包含功能,而不是复制它。但作为一项学术活动,我想一切都会发生…@nikic:这实际上是误导。
-w
选项应该
输出带有精简注释和空白的源代码。
-但它主要只是压缩它们。作为一个例子,这很有趣。是的,我知道php-w命令。徒劳可能有点过于戏剧化,我只想要一个一键函数,去掉我不需要的东西,并替换变量。谢谢你的推荐,很有趣。剧本很好,谢谢。它还与一个变量替换器一起工作。我在令牌上运行两个循环,首先捕获变量,然后在第二个循环中删除空白,然后替换变量。我还删除了注释,发现如果我尝试在一个循环中删除注释,那么注释原来所在的位置会有一个空间。在我的例子中,我将它移动到第一个循环,所有问题都解决了。*我发现除了“case”语句之外,这对我的许多文件都有效。例如,我的一个语句是检查http状态,而“case404:”变成了“case404:”,这显然是一个错误。我只是将那个else设置为elseif($token[0]==T_CASE){$new_source.=$token[1].';}(在标记后添加一个空格),然后继续执行当前的else语句。@Matt Gaidica:是的,我的错。我检查了PHP lexer定义为
{LABEL}
的内容,但我也应该查找数字,因为它们也可以出现在标签中(除了第一个字符)。我调整了正则表达式。
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;
}