Re: [SLUG] String Replacement

From: Paul Legato (pjlegato@tampabay.rr.com)
Date: Wed Jul 04 2001 - 02:33:32 EDT


Hi,
There are faster ways to do this with bash and sed, but the syntax is a bit
more cryptic than Perl and it will only be negligibly faster on a job of
100 files or so.

Crash Perl tutorial: Make a Perl script. Type the following in your favorite
text editor and save it as sar.pl.

-- begin cut --
#!/usr/bin/perl -w
# ^^ this line tells the kernel what scripting language interpreter to use
# (in this case /usr/bin/perl with the -w "warnings on" switch. Your perl
# might also be in /usr/local/bin/perl.)

   # Global variables.
  $original = "Jim";
  $changeto = "Jim H.";

  # Open the . directory (current directory) and associate it with the
  # filehandle DIR. Exit if unable to open.
  opendir DIR, "." or die "Don't have read access to current directory!";

  # foreach loops over the array and executes its code block
  # with $_ assigned each subsequent value of the array inside the ().
  # readdir DIR returns an array of the directory entries for DIR.

  foreach(readdir DIR)
    {
        open INFILE, "<$_"; # Open current filename for reading (the "<") and
                          # associate with symbol "INFILE"

        open OUTFILE, ">$_.new"; # open new file for output
                                   # use the original filename with a .new extension

        # Print a warning and skip this file unless we got an INFILE and an OUTFILE
        # above.
        unless(INFILE and OUTFILE)
          {
                print "Couldn't process $_ -- skipping...\n"; #"\n" means newline
                next;
          } # end unless

        print "Processing $_..."; # notice no "\n" - stays on the same line
                                # $_ will be replaced with the current filename

        while(<INFILE>) # The angle brackets <> read the next line from INFILE
                        # into $_.
          { # while() repeats its block until there's a null inside the ()
                        # (which is what happens with <> when you reach the
                        # end of the file, EOF).
                

                s/$original/$changeto/g; # (s)earch for $original, change it to
                                        # $changeto, and make the search
                                        # (g)lobal (i.e. all occurances in the string)

                print OUTFILE $_; # Print the line to the output file
          } # end while

        print " Done.\n"; # print "Done." on the same line as "Processing..." above.

        close INFILE; # close the filehandles so they can be reused next loop.
        close OUTFILE;

    } # end foreach

   print "All done.\n";
   closedir DIR; # close the directory handle

-- end cut --

Then type "chmod +x sar.pl" to mark the script as executable by the kernel.

Type "/path/to/sar.pl" to run it on the current directory. Note that you
probably don't want to keep the file sar.pl itself in the directory you're
running it on or else it will change the '$original = "Jim"' to '$original =
"Jim H."'! It searches all files in the current directory for whatever
$original is and write a new file called filename.new with all occurances of
$original changed to $changeto.

This is just the tip of the iceberg of what's possible with Perl. Check out
http://www.perl.com/ and http://www.perldoc.com/ if you want to know more..
This script could be modified without too much trouble to e.g., read its
arguments (directory to process, $original, and $changeto) from the command
line or to just modify the original file instead of creating another file
with a .new extension (hint: use a temporary file with link and unlink)...

Good luck..
-Paul

On Wednesday 04 July 2001 03:55 am, you wrote:
> Non / soon to be member submission:
> This may be simple, but i'm reading and reading and I can't find out
> how. What i'm trying to do is a string replacement in many txt files at
> once. Say theres 100 files with the name Jim in them and I want to
> replace "Jim" with "Jim H". I can manually do it one by one with emacs,
> but there may be thousands of needed replacements and that would take
> OMG way too long.
>
> Any help?
>
> Thanks in advance.



This archive was generated by hypermail 2.1.3 : Fri Aug 01 2014 - 15:29:08 EDT