Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Oh wise Monks, I'm new to perl in a unix enviroment, and want to know the best way to do a search of text in a known filename ($filename) for a url in the format http://domain.com/folder/subfolder replacing it with http://domain.com/newfolder/newsubfolder/$localvar where $localvar will be some directory name that is generated by the perl code. I'd like to do it without having to open each file inside of perl. I was thinking a system call with the 'tr' command would work, but it doesn't appear to. Any Ideas?
  • Comment on search and replace text in multiple files in a directory

Replies are listed 'Best First'.
Re: search and replace text in multiple files in a directory
by davido (Cardinal) on Apr 02, 2005 at 16:47 UTC

    tr/// is the transliteration operator, good for converting individual characters into some other character (or counting, or deleting individual characters). It's not helpful in this case.

    You actually want to look at the s/// substitution operator, for what you're trying to accomplish. Here is a description of what to do:

    open $filename for reading. Open a temporary file for output. Scan through $filename line by line using the while( <INFILE> ) {..... construct. Inside the loop, on each line, use the substitution operator to identify matches, and substitute for your new text. Then print each line back out to your temp file. After the loop terminates, close both file handles, and rename the temp file to replace the original file.

    If you're operating in a multi-user or web server context, file locking will also be advisable.


    Dave

Re: search and replace text in multiple files in a directory
by borisz (Canon) on Apr 02, 2005 at 15:08 UTC
    Probably I missunderstand the question.
    perl -i.orig -pe 'BEGIN{$localvar = "xyz"}; s!http://domain.com/folder +/subfolder!http://domain.com/newfolder/newsubfolder/$localvar!g' your +_filename more_files
    Boris
Re: search and replace text in multiple files in a directory
by willyyam (Priest) on Apr 02, 2005 at 19:46 UTC

    What I do is I have a script in my ~/bin directory called fixfile.pl that looks like this:

    !/usr/bin/perl -p -i s/expression_to_replace/replacement_expression/gs;

    My program is much longer, because each time I find a regex that works I leave it in the program, commented, and add my new regex. That way I create a library of useful regexes. To use the program I just go to the directory I want to make the changes in, and run (for your example) fixfile.pl *.html and the regex is performed on all files with the extension .html. The reason I find this useful is because I can leverage the power of a perl one-liner without losing the record of what I've been doing, and it lets me use my familiar shell globbing operators.

      I think the script you are trying to write can be wrote with Tie::File . Read the documentation about it.
Re: search and replace text in multiple files in a directory
by steelrose (Scribe) on Apr 04, 2005 at 15:03 UTC
    It really depends on whether you want to actually open each file in the perl program itself, or let the OS do that for you. I do something similiar to the latter, where I make a system call: system ("sed 's/$searchString/$replacementString/g $filename > $newFilename'"); Note that I'm creating a NEW file with the changed text and not overwriting the original.
    If you give a man a fish he will eat for a day. If you teach a man to fish he will buy an ugly hat. If you talk about fish to a starving man, you're a consultant.