用<?php替换PHP短开标签的批处理脚本

Pol*_*eme 18 php awk sed find

我有很多年来编写的大量php文件,我需要将所有短开标签正确替换为正确的显式开放标签.

change "<?" into "<?php"
Run Code Online (Sandbox Code Playgroud)

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

<\?(\s|\n|\t|[^a-zA-Z])
Run Code Online (Sandbox Code Playgroud)

照顾像这样的案件

<?//
<?/*
Run Code Online (Sandbox Code Playgroud)

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

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

也许我错了.
或许这可能是一个oneliner?

ax.*_*ax. 16

不要使用正则表达式来解析正式语言 - 你总会遇到你没想到的干草堆.喜欢:

<?
$bla = '?> now what? <?';
Run Code Online (Sandbox Code Playgroud)

使用知道语言结构的处理器更安全.对于html,这将是一个xml处理器; 对于php,内置的tokenizer扩展.它有T_OPEN_TAG解析器令牌,匹配<?php,<?<%,和T_OPEN_TAG_WITH_ECHO,匹配<?=<%=.替换所有短开的标签,你会发现所有这些令牌和更换T_OPEN_TAG<?php,并T_OPEN_TAG_WITH_ECHO<?php echo.

实施留给读者的练习:)

编辑1:指挥官是如此善良提供一个.

编辑2:与系统short_open_tag中关闭了php.ini,<?,<%,并<?=不会被替代脚本的认可.要使脚本在此类系统上运行,请short_open_tag通过命令行选项启用:

php -d short_open_tag=On short_open_tag_replacement_script.php
Run Code Online (Sandbox Code Playgroud)

ps token_get_all()的手册页和googleing for tokenizer,token_get_all和解析器令牌名称的创意组合可能有所帮助.

pps还看到Regex解析define()内容,可能吗?在这里

  • @Polypheme:<?xml version ="1.0"encoding ="UTF-8"?> (2认同)

rin*_*ter 14

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

$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;
Run Code Online (Sandbox Code Playgroud)

请注意,如果未启用短标记,则标记生成器将无法正确标记短标记.也就是说,您无法在短标签不起作用的系统上运行此代码.您必须在其他地方运行它来转换代码.


hak*_*kre 5

作为 工具中的固定器,已经解决了该问题,该php-cs-fixer工具可以轻松安装并经过测试和维护。

然后修复很容易:

$ php-cs-fixer fix --fixers=short_tag --diff --dry-run <path>
Run Code Online (Sandbox Code Playgroud)

只需替换<path>为您要更改的目录或文件的路径即可。给定的命令是首先检查(--dry-run--diff参数)。

安装就像

$ composer global require friendsofphp/php-cs-fixer
Run Code Online (Sandbox Code Playgroud)

如果您已经在路径中安装了composer并在全局composer bin目录中安装(推荐)。

  • 最新版本的php-cs-fixer使用以下语法:```php-cs-fixer fix --rules = full_opening_tag --diff --dry-run .`'' (2认同)

Ken*_*ric 3

我之前的答案只是用 sed 覆盖了,这是行不通的,在我看来,sed 对于这类事情来说太弱了。

所以我编写了一个 perl 脚本来解决这个问题,希望它是用户可编辑的。

#!/usr/bin/perl 

use strict;
use warnings;

use File::Find::Rule;
use Carp;

my @files = File::Find::Rule->file()->name('*.php')->in('/tmp/foo/bar');

for my $file (@files) {
    rename $file, $file . '.orig';
    open my $output, '>', $file or Carp::croak("Write Error with $file $! $@ ");
    open my $input, '<', $file . '.orig'
      or Carp::croak("Read error with $file.orig $! $@");

    while ( my $line = <$input> ) {
        # Replace <?= with <?php echo 
        $line =~ s/<\?=/<?php echo /g;

        # Replace <? ashded  with <?php ashed

        $line =~ s/<\?(?!php|xml)/<?php /g;
        print $output $line;
    }

    close $input  or Carp::carp(" Close error with $file.orig, $! $@");
    close $output or Carp::carp(" Close error with $file  , $! $@");

    unlink $file . '.orig';
}
Run Code Online (Sandbox Code Playgroud)

但请注意,我还没有在任何实际代码上测试过这个,所以它可能会“爆炸”。

我建议你修改你的代码(等等,它已经修改了,对吧?..对吗?)并在修改后的代码上运行你的测试套件(不要告诉我你没有测试!),因为你可以如果没有成熟的 FSM 解析器,不确定它是否做正确的事情。