批处理脚本,用于将 PHP 短开放标记替换为 <?php

2022-08-30 19:40:43

多年来,我有大量的php文件,我需要将所有短的开放标签正确地替换成适当的显式开放标签。

change "<?" into "<?php"

我认为这个正则表达式会正确地选择它们:

<\?(\s|\n|\t|[^a-zA-Z])

它处理以下情况

<?//
<?/*

但我不确定如何处理整个文件夹树并检测.php文件扩展名并应用正则表达式并在更改后保存文件。

我觉得如果你掌握了正确的工具,这可能非常简单。(sed手册中有一个有趣的技巧:4.3示例/将文件重命名为小写)。

也许我错了。
或者,也许这可以是一个单线?


答案 1

不要使用正则表达式来解析形式语言 - 你总是会遇到你没有预料到的大海捞针。喜欢:

<?
$bla = '?> now what? <?';

使用了解语言结构的处理器更安全。对于html,那将是一个xml处理器;对于 php,内置的分词器扩展。它具有T_OPEN_TAG解析器令牌,该令牌匹配 , 或 , 和 T_OPEN_TAG_WITH_ECHO 匹配 或 。要替换所有短的打开标记,请找到所有这些标记并替换为 和 。<?php<?<%<?=<%=T_OPEN_TAG<?phpT_OPEN_TAG_WITH_ECHO<?php echo

实现留给读者练习:)

编辑1:Ringmaster非常好心地提供了一个

编辑 2:在 short_open_tag、 中关闭的系统,替换脚本无法识别。要使脚本在此类系统上工作,请通过命令行选项启用:php.ini<?<%<?=short_open_tag

php -d short_open_tag=On short_open_tag_replacement_script.php

p.s. token_get_all() 的手册页和 googleing 的分词器token_get_all和解析器令牌名称的创造性组合可能会有所帮助。

p.p.s. 另请参阅正则表达式来解析 define() 内容,可能吗? 这里在 SO 上


答案 2

如果您使用的是分词器选项,这可能会有所帮助:

$content = file_get_contents($file);
$tokens = token_get_all($content);
$output = '';

foreach($tokens as $token) {
 if(is_array($token)) {
  list($index, $code, $line) = $token;
  switch($index) {
   case T_OPEN_TAG_WITH_ECHO:
    $output .= '<?php echo ';
    break;
   case T_OPEN_TAG:
    $output .= '<?php ';
    break;
   default:
    $output .= $code;
    break;
  }

 }
 else {
  $output .= $token;
 }
}
return $output;

请注意,如果未启用短标记,分词器将无法正确标记短标记。也就是说,您无法在短标记不起作用的系统上运行此代码。您必须在其他位置运行它才能转换代码。


推荐