2010-01-29 22 views
8

के साथ प्रतिस्थापित करता है मैं PHP में पूरी फ़ाइल के लिए स्ट्रिंग को प्रतिस्थापित करने का प्रयास कर रहा हूं। मेरी फ़ाइल 100 एमबी से अधिक है इसलिए मुझे लाइन से लाइन जाना है और file_get_contents() का उपयोग नहीं कर सकता है। क्या इसका कोई अच्छा समाधान है?स्ट्रिंग एक बड़ी फ़ाइल में php

+2

क्या PHP का उपयोग करना आवश्यक है? यदि आपके पास कमांड लाइन तक पहुंच है, तो आप एक ही फ़ंक्शन को करने के लिए 'sed' कमांड का उपयोग कर सकते हैं, शायद सिरदर्द के बहुत कम के साथ। अगर इसे स्वचालित करने की आवश्यकता है, तो आप एक शेल स्क्रिप्ट बना सकते हैं जो क्रॉन पर चलता है। –

+1

सहमत हैं, यह कमांड लाइन के लिए कुछ है, PHP नहीं। – Mike

उत्तर

10

यदि आपको PHP का उपयोग करने की आवश्यकता नहीं है, तो मैं कमांड लाइन से इस तरह की सामग्री को करने की अत्यधिक अनुशंसा करता हूं। यह नौकरी के लिए सबसे अच्छा उपकरण है, और उपयोग करने के लिए बहुत आसान है।

किसी भी मामले में, sed आदेश आप के लिए क्या देख रहे है:

sed s/search/replace oldfilename > newfilename 

आप केस-असंवेदनशीलता की जरूरत है:

sed -i s/search/replace oldfilename > newfilename 

आप इस गतिशील भीतर प्रदर्शन करने की जरूरत है PHP, आप passthru() का उपयोग कर सकते हैं:

$output = passthru("sed s/$search/$replace $oldfilename > $newfilename"); 
+1

क्यों 'passthru() 'और' exec() '? – Brian

+3

या तो काम करेगा, लेकिन पासस्ट्रू का उपयोग करके, आप संपूर्ण आउटपुट प्राप्त कर सकते हैं। निष्पादन केवल आउटपुट की अंतिम पंक्ति देता है। –

+0

पैडस्ट्रू को कॉल करने के लिए उपयोग करना इतना आसान नहीं है, विवरण के लिए मेरा उत्तर देखें। –

1

इसे एक समय में कुछ पंक्तियां प्राप्त करें, चर को डंप करें, अगली कुछ पंक्तियां प्राप्त करें।

$fh = fopen("bigfile.txt", "flags"); 
$num = 0; 
$length = 300; 
$filesize = filesize("bigfile.txt"); 

while($num < $filesize) 
{ 
    $contents = fread($fh, $length); 
    // .. do stuff ... 
    $num = $num+$length; 
    fseek($fh, $num); 
} 

fclose($fh); 

आप यह सुनिश्चित करना चाहते हैं कि यह सही है (परीक्षण नहीं किया गया है)। PHP Documentation.

पर लाइब्रेरी देखें, मुश्किल हिस्सा फ़ाइल पर वापस लिखने जा रहा है। मेरे दिमाग में आने वाला पहला विचार स्ट्रिंग को प्रतिस्थापित करता है, नई सामग्री को दूसरी फ़ाइल में लिखें, और फिर अंत में, पुरानी फ़ाइल को हटाएं और इसे नए से बदलें।

+0

हाँ यह सही है ... एक गरीब आदमी की स्ट्रीमिंग।यह प्रभावी ढंग से कैसे काम करेगा यदि आपने इसे कमांड लाइन पर किया था: बिल्ली फ़ाइल | sed's/replace/something/g '> output.file – mlathe

+0

मैं एक php स्क्रिप्ट चलाऊंगा जिसे कमांड लाइन फ़ंक्शन कहा जाता है - फिर आउटपुट फ़ाइल मुद्रित करें :) – Dirk

+1

यदि आप जिस स्ट्रिंग को देख रहे हैं, तो इस विधि में कोई समस्या है प्रतिस्थापित करने के लिए एक वर्ण से अधिक लंबा है। यह काफी संभव है कि स्ट्रिंग डेटा के कई हिस्सों को फैला सकती है, जिससे आप प्रतिस्थापन को छोड़ सकते हैं। – bish

6

ये रहा:

function replace_file($path, $string, $replace) 
{ 
    set_time_limit(0); 

    if (is_file($path) === true) 
    { 
     $file = fopen($path, 'r'); 
     $temp = tempnam('./', 'tmp'); 

     if (is_resource($file) === true) 
     { 
      while (feof($file) === false) 
      { 
       file_put_contents($temp, str_replace($string, $replace, fgets($file)), FILE_APPEND); 
      } 

      fclose($file); 
     } 

     unlink($path); 
    } 

    return rename($temp, $path); 
} 

यह कॉल इस तरह:

replace_file('/path/to/fruits.txt', 'apples', 'oranges'); 
+0

मैं बस अनुमान लगा रहा हूं कि आप इस समारोह को झूठ बोल रहे थे? –

+1

@ चाचा 102: नहीं, मैंने बस इसे कोड किया। क्यूं कर? –

+5

यह एक मजाक था। मुझे नहीं पता कि यह मजाकिया क्यों होगा। मैं इसे अपने जेडीटी (जोक डेवलपमेंट टीम) को देने जा रहा हूं और 6 से 8 सप्ताह में आपको वापस ले जाऊंगा। –

1

कुछ इस तरह?

$infile="file"; 
$outfile="temp"; 
$f = fopen($infile,"r"); 
$o = fopen($outfile,"a"); 
$pattern="pattern"; 
$replace="replace"; 
if($f){ 
    while(!feof($f)){ 
     $line = fgets($f,4096); 
     if (strpos($pattern,"$line") !==FALSE){ 
      $line=str_replace($pattern,$replace,$line); 
     } 
     fwrite($o,$line); 
    } 
} 
fclose($f); 
fclose($o); 
rename($outfile,$infile); 
1

मैं 'sed' का उपयोग अधिक स्पष्ट तरीके से करता था, इसलिए आप अपने सिस्टम पर कम निर्भर हैं।

$output = passthru("sed -e 's/$search/$replace/g' $oldfilename > $newfilename"); 
2

आप सीधे का उपयोग कमांड लाइन से sed नहीं कर सकते, क्योंकि यह एक गतिशील काम है और आप इसे php से कॉल करने की आवश्यकता यह वाक्य रचना सही पाने के लिए मुश्किल है: आपके द्वारा खोज और प्रतिस्थापन में अलग अलग तरीकों से पलायन करना होगा इन पात्रों

'/$ . * [ ] \^& 

निम्नलिखित समारोह तलाश किए जाने और एक नियमित अभिव्यक्ति के रूप में की खोज स्ट्रिंग की व्याख्या के बिना एक फ़ाइल में एक स्ट्रिंग की जगह। तो यदि आप चाहते थे कि आप "। *" स्ट्रिंग की खोज कर सकें और इसे "$" से प्रतिस्थापित कर सकें।

/** 
* 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; 
} 
संबंधित मुद्दे