从Bash脚本修改PHP文件

从Bash脚本修改PHP文件,php,html,regex,bash,parsing,Php,Html,Regex,Bash,Parsing,我需要从Bash脚本对PHP文件(确切地说是PHTML文件,但它们仍然是有效的PHP文件)执行一些修改。我最初的想法是在regex中使用sed或类似的实用程序,但是阅读这里关于其他HTML解析问题的一些回复,似乎有更好的解决方案 我在正则表达式中遇到的问题是缺少对检测我想要匹配的字符串的支持:(src | href | action)=[“']/是否在标记中,因此如果匹配在PHP标记中,我可以执行字符串连接,如果不在PHP标记中,则可以添加新的PHP标记。例如: (1) <img id="

我需要从Bash脚本对PHP文件(确切地说是PHTML文件,但它们仍然是有效的PHP文件)执行一些修改。我最初的想法是在regex中使用sed或类似的实用程序,但是阅读这里关于其他HTML解析问题的一些回复,似乎有更好的解决方案

我在正则表达式中遇到的问题是缺少对检测我想要匹配的字符串的支持:
(src | href | action)=[“']/
是否在
标记中,因此如果匹配在PHP标记中,我可以执行字符串连接,如果不在PHP标记中,则可以添加新的PHP标记。例如:

(1) <img id="icon-loader-small" src="/css/images/loader-small.gif" style="vertical-align:middle; display:none;"/>
(2) <li><span class="name"><?php echo $this->loggedInAs()?></span> | <a href="/Login/logout">Logout</a></li>
(3) <?php echo ($watched_dir->getExistsFlag())?"":"<span class='ui-icon-alert'><img src='/css/images/warning-icon.png'></span>"?><span><?php echo $watched_dir->getDirectory();?></span></span><span class="ui-icon ui-icon-close"></span>
(EDIT: 4) <form method="post" action="/Preference/stream-setting" enctype="application/x-www-form-urlencoded" onsubmit="return confirm('<?php echo $this->confirm_pypo_restart_text ?>');">
(1)
(2) 
  • |

  • (3) 我解决这个问题的方法是将我的文件分成由封装的部分。脚本跟踪它当前所在的“上下文”-默认设置为html,但遇到这些标记时切换到php。操作(不一定是正则表达式)然后在该节上执行,然后将该节附加到输出缓冲区。当文件完成处理后,输出缓冲区将写回文件

    我试图用sed实现这一点,但我面临的问题是无法控制换行符将在何处打印。基于上下文的逻辑也是硬编码的,这意味着在新上下文中添加会很乏味,例如ASP.NET支持。我当前的解决方案是用Perl编写的,可以缓解这两个问题,尽管我有点担心很难让我的正则表达式实际执行某些操作,但这可能只是我对正则表达式的编码不正确

    脚本如下:

    #!/usr/bin/perl -w
    
    use strict;
    
    #Prototypes
    sub readFile(;\$);
    sub writeFile($);
    
    #Constants
    my $file;
    my $outputBuffer;
    my $holdBuffer;
    # Regexes should have s and g modifiers
    # Pattern is in $_
    my %contexts = (
        html => {
            operation => ''
        },
        php => {
            openTag => '<\?php |<\? ', closeTag => '\?>', operation => ''
        },
        js => {
            openTag => '<script>', closeTag => '<\/script>', operation => ''
        }
    );
    my $currentContext = 'html';
    my $combinedOpenTags;
    
    #Initialisation
    unshift(@ARGV, '-') unless @ARGV;
    foreach my $key (keys %contexts) {
        if($contexts{$key}{openTag}) {
            if($combinedOpenTags) {
                $combinedOpenTags .= "|".$contexts{$key}{openTag};
            } else {
                $combinedOpenTags = $contexts{$key}{openTag};
            }
        }
    }
    
    #Main loop
    while(readFile($holdBuffer)) {
        $outputBuffer = '';
        while($holdBuffer) {
            $currentContext = "html";
            foreach my $key (keys %contexts) {
                if(!$contexts{$key}{openTag}) {
                    next;
                }
                if($holdBuffer =~ /\A($contexts{$key}{openTag})/) {
                    $currentContext = $key;
                    last;
                }
            }
            if($currentContext eq "html") {
                $holdBuffer =~ s/\A(.*?)($combinedOpenTags|\z)/$2/s;
                $_ = $1;
            } else {
                $holdBuffer =~ s/\A(.*?$contexts{$currentContext}{closeTag}|\z)//s;
                $_ = $1;
            }
            eval($contexts{$currentContext}{operation});
            $outputBuffer .= $_;
        }
        writeFile($outputBuffer);
    }
    
    # readFile: read file into $_
    sub readFile(;\$) {
        my $argref = @_ ? shift() : \$_;
        return 0 unless @ARGV;
        $file = shift(@ARGV);
        open(WORKFILE, "<$file") || die("$0: can't open $file for reading ($!)\n");
        local $/;
        $$argref = <WORKFILE>;
        close(WORKFILE);
        return 1;
    }
    
    # writeFile: write $_[0] to file
    sub writeFile($) {
        open(WORKFILE, ">$file") || die("$0: can't open $file for writing ($!)\n");
        print WORKFILE $_[0];
        close(WORKFILE);
    }
    
    !/usr/bin/perl-w
    严格使用;
    #原型
    子读取文件(;\$);
    子写入文件($);
    #常数
    我的$file;
    我的$outputBuffer;
    我的$holdBuffer;
    #正则表达式应该有s和g修饰符
    #图案在里面$_
    我的%contexts=(
    html=>{
    操作=>“”
    },
    php=>{
    openTag=>'',操作=>''
    },
    js=>{
    openTag=>“”,closeTag=>“”,operation=>“”
    }
    );
    my$currentContext='html';
    我的$combinedOpenTags;
    #初始化
    取消移位(@ARGV,'-'),除非@ARGV;
    foreach my$key(key%上下文){
    if($contexts{$key}{openTag}){
    如果($combinedOpenTags){
    $combinedOpenTags.=“|”。$contexts{$key}{openTag};
    }否则{
    $combinedOpenTags=$contexts{$key}{openTag};
    }
    }
    }
    #主回路
    while(readFile($holdBuffer)){
    $outputBuffer='';
    while($holdBuffer){
    $currentContext=“html”;
    foreach my$key(key%上下文){
    if(!$contexts{$key}{openTag}){
    下一个
    }
    if($holdBuffer=~/\A($contexts{$key}{openTag})/){
    $currentContext=$key;
    最后;
    }
    }
    if($currentContext eq“html”){
    $holdBuffer=~s/\A(.*)($combinedPentags |\z)/$2/s;
    $_ = $1;
    }否则{
    $holdBuffer=~s/\A(.*?$contexts{$currentContext}{closeTag}|\z)//s;
    $_ = $1;
    }
    eval($contexts{$currentContext}{operation});
    $outputBuffer.=$\uU3;
    }
    writeFile($outputBuffer);
    }
    #readFile:将文件读入$_
    子读取文件(;\$){
    我的$argref=@\ux?shift():\$\ux;
    返回0,除非@ARGV;
    $file=shift(@ARGV);
    
    打开(工作文件,”这就是为什么表示层应该与应用程序逻辑混淆的主要原因之一。我相信你的意思是:不应该很难说出你真正想要做什么,但如果它涉及到解析任意PHP以找到你想要的内容,regexps根本无法做到这一点。PHP有上下文无关的语法,而regexe无法解析这些语法。你可以随时放弃n可靠的解析,只需使用正则表达式和偶尔的中断即可;这是您必须做出的决定,但大多数情况下,这条路径的结局很糟糕,因为它不断地回来咬您。如果正则表达式不是它,您需要一个真正的PHP解析器。