View Source

<p>Hi Team!</p>

<p>I collected my notes regarding techniques for global search and replace. As always, excercise caution and check carefully before committing. Sometimes a simple change must be made to all language versions of a file. Instead of asking every single language translation team to make the same repetitive edits, consider using a global search and replace.</p>

<p>If some text exists in multiple files and the same change must be made in several files, there are several ways to make these changes:</p>

<h3>Alternative Methods for Search and Replace</h3>
<ol>
<li>Use a GUI text editor that can safely perform search and replace on many files containing UTF8 text</li>
<li>Use a command line tool (described below) to make the changes. This option works well for more complex changes.</li>
<li>Make the changes by hand to each file.</li>
<li>Describe the change, and a programmer can use a tool to automate the changes. For example, the description below for &quot;Zend_Inputfilter&quot; =&gt; &quot;Zend_Filter_Input&quot; is good.</li>
</ol>


<p>Next, either post a patch file or the command line used with a bug report (ticket), or test and commit to svn, if you have SVN commit permission for all the affected files and don't believe the issue should have its own bug report.</p>

<h3>Option #2 (for programmers)</h3>

<p>Create and test a needed global change on your local copy (commit your changes <strong>before</strong> testing, apply global search and replace, then &quot;svn revert&quot; can undo, if the changes cause any problems).</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$ |svn checkout http://framework.zend.com/svn/framework/trunk framework
.
.
$ cd framework/documentation/manual
|$ find . -path '*/.svn' -prune , -type f -a -iname '*.xml' | xargs
./sed.php '/Zend_InputFilter/u' 'Zend_Filter_Input'
.
.
$ svn status
M en/module_specs/Zend_Filter.xml
M pt-br/module_specs/Zend_Filter.xml
M ru/module_specs/Zend_Filter.xml
M es/module_specs/Zend_Filter.xml
M fr/module_specs/Zend_Filter.xml
M ja/module_specs/Zend_Filter.xml
M pl/module_specs/Zend_Filter.xml

$ cat sed.php
#!/usr/local/bin/php-cli
<?php
# Usage: ./sed.php '/pcre expression/u' 'replacement text' filename
[filename]...
# Synopsis: behaves like sed -i -e 's/expression/replacement text/g'
# http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php -
also see comments
array_shift($argv);
$pattern=array_shift($argv);
$replacement=array_shift($argv);
echo "pattern=$pattern\n";
echo "replacement=$replacement\n";

foreach ($argv as $fn)
{
$f = file_get_contents($fn,false);
if ($f === FALSE) continue;
$f2 = preg_replace($pattern, $replacement, $f);
if ($f === $f2) continue;
if (strlen($f2) < 1) continue;
if (file_put_contents("$fn.tmp", $f2) < 1)
{
fwrite(STDERR, "WARNING: Writing to '$fn' failed.\n");
continue;
}
#rename is usually atomic, so if the script is interrupted, we
shouldn't have corrupted source files
if (false === rename("$fn.tmp", $fn))
{
fwrite(STDERR, "WARNING: Unable to rename '$fn.tmp' to
'$fn'.\n");
continue;
}
echo "$fn\n";
}
]]></ac:plain-text-body></ac:macro>

<p>Cheers,<br />
Gavin</p>

<p>P.S. From Cygwin, I type:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$ find . -path '*/.svn' -prune , -type f -a -iname '*.xml' | xargs grep
Zend_InputFilter
Then I tried:
$ find . -path '*/.svn' -prune , -type f -a -iname '*.xml' | xargs sed
-i -e 's/Zend_InputFilter/Zend_Filter_Input/g'
]]></ac:plain-text-body></ac:macro>

<p>The &quot;sed&quot; in Cygwin (<a class="external-link" href="http://www.gnu.org/software/sed/manual/html_mono/sed.html">http://www.gnu.org/software/sed/manual/html_mono/sed.html</a>), does not claim to understand UTF8, which would lead to certain cases where this sed will produce undesirable results. Regardless, using a PHP replacement for sed that uses PCRE is just plain cool 8^).</p>