string replace in a large file with php

后端 未结 6 1913
借酒劲吻你
借酒劲吻你 2020-12-09 12:41

I am trying to do a string replace for entire file in PHP. My file is over 100MB so I have to go line by line and can not use file_get_contents(). Is there a

6条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-09 12:58

    If you can't use directly sed from command line because it's a dynamic task and you need to call it from php it's difficult to get the syntax right: you must escape in different ways in the search and replacement strings these characters

    ' / $ . * [ ] \ ^ &
    

    The following function search and replace a string in a file without interpreting the searched string as a regular expression. So if you wanted you could search for the string ".*" and replace it with "$".

    /**
     * str_replace_with_sed($search, $replace, $file_in, $file_out=null)
     * 
     * Search for the fixed string `$search` inside the file `$file_in`
     * and replace it with `$replace`. The replace occurs in-place unless
     * `$file_out` is defined: in that case the resulting file is written
     * into `$file_out`
     *
     * Return: sed return status (0 means success, any other integer failure)
     */
    function str_replace_with_sed($search, $replace, $file_in, $file_out=null)
    {
        $cmd_opts = '';
        if (! $file_out) 
        {
            // replace inline in $file_in
            $cmd_opts .= ' -i';
        }
    
        // We will use Basic Regular Expressions (BRE). This means that in the 
        // search pattern we must escape
        // $.*[\]^
        //
        // The replacement string must have these characters escaped
        // \ & 
        //
        // In both cases we must escape the separator character too ( usually / )
        // 
        // Since we run the command trough the shell we We must escape the string
        // too (yai!). We're delimiting the string with single quotes (') and we'll
        // escape them with '\'' (close string, write a single quote, reopen string)    
    
        // Replace all the backslashes as first thing. If we do it in the following
        // batch replace we would end up with bogus results
        $search_pattern = str_replace('\\', '\\\\', $search);
    
        $search_pattern = str_replace(array('$', '.', '*', '[', ']', '^'),
                                      array('\\$', '\\.', '\\*', '\\[', '\\]', '\\^'),
                                      $search_pattern);
    
        $replace_string = str_replace(array('\\', '&'),
                                      array('\\\\', '\\&'),
                                      $replace);
    
        $output_suffix = $file_out ? " > '$file_out' " : '';
        $cmd = sprintf("sed ".$cmd_opts." -e 's/%s/%s/g' \"%s\" ".$output_suffix,
                        str_replace('/','\\/', # escape the regexp separator
                          str_replace("'", "'\''", $search_pattern) // sh string escape
                        ),
                        str_replace('/','\\/', # escape the regexp separator
                          str_replace("'", "'\''", $replace_string) // sh string escape
                        ),
                        $file_in
                      );
    
        passthru($cmd, $status);
    
        return $status;
    }
    

提交回复
热议问题