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

Hello dear PERL MONKS!

I am new to PERL, and i tryed to create a programm, which searches all FILES in the same directory as the programm is placed FOR a word that i type in and REPLACES it for NEXT WORD that i also type in ...

EXAMPLE: I hit start, it asks what word shall be replaced? I type in GIF. Which word shall be there in stead o GIF? I type in IMG. I hit ENTER and it shall search the whole directory for the word GIF and replace it with IMG.

My programm, which i made works on the same way, but it has some disadvantages. It does not SEARCH - i have no idea how to make it, i have to write always the name of the file which i want to be edited ... I tryed Tutorials but they did not help ... And the second disadvantage is, that it waork only with the first line of my TEXT FILE .. I also have no idea why ...

Could you please help me solve this two problems? Here is my source:

use warnings; system"cls"; print "Which TEXT File shall be changhed?\n"; my $datname = <STDIN>; chomp($datname); open(READFILE,"<$datname"); my $erssetz = <READFILE>; close(READFILE); print "\n"; my $vor = $erssetz; print "Which word you want to be REPLACED? \n"; my $wort = <STDIN>; chomp($wort); print "\n"; print "What word shall be there the REPLACER? \n"; my $ersetz = <STDIN>; chomp($ersetz); print "\n"; $erssetz =~ s/$wort/$ersetz/g; open(WRITEFILE,">Ersetzt_$datname"); print WRITEFILE $erssetz; close(WRITEFILE); print "Finished -> saved AS : REPLACED_$datname \n";

Replies are listed 'Best First'.
Re: Word Replacing
by moritz (Cardinal) on May 31, 2007 at 13:22 UTC
    First of all, Perl is case sensitive, and it's not "PERL".

    If you just want to replace a word, you don't even need a script:

    perl -pi.orig -e 's/original/substitute/g' <filename>
    
    Update: If you want to get your script working, you should iterate over all lines in the file, and not just work with the first line.

    Each time you read something from <FILEHANDLE> in scalar context it reads one line.

    Perhaps you should find a good book to learn Perl from.

      perl -pi.orig -e 's/original/substitute/g' <filename>

      (To the OP:) if you want that to apply to a large number of files, all in the same directory, just give them on the cmd line. That is, <filename> can really be <filenames> or a shell pattern that the shell will expand. If the files are too many for the shell to handle, then as I wrote in my other reply do so yourself with glob:

      perl -pi.orig -e 'BEGIN{@ARGV=map glob, @ARGV} s/original/substitute/g +' '*.foo' 'bar.*'

      Note that this is also necessary under Windows, where the shell does not do expansions at all. But in that case you have to use double quotes instead of single ones.

      A reply falls below the community's threshold of quality. You may see it by logging in.
      hmmm .. ok .. but if i want that it will search, check and replace all words in all files in a folder? look, i have for example about 1000 TXT files, and there is a word Bartholome and i need to replace it for Richard - In ALL files in this folder ... Yes i know .. I do perl mostly for fun, but i need it now .. :(
            look, i have for example about 1000 TXT files, and there is a word Bartholome and i need to replace it for Richard

        Similar to what was already pointed out to you:

        perl -spi -e 's/Bartholome/Richard/g' /path/to/folder/*


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
        hmmm .. ok .. but if i want that it will search, check and replace all words in all files in a folder?

        Use glob or File::Find (if you want to do that recursively) or one of its friendlier relatives.

Re: Word Replacing
by blazar (Canon) on May 31, 2007 at 13:49 UTC
    Could you please help me solve this two problems? Here is my source:

    Far too many problems to deal with all of them in an amount of time that could be reasonable for me now. Just some hints:

    • "PERL";
    • no strict - too bad!
    • weird style;
    • "old style", unchecked opens;
    • no proper iteration over the lines of a file nor slurping nor... anything!

    Please do not take it as a personal offense, but it seems to me that you're trying to do something in Perl without even having a clue about the very basics of the language. All in all you may well be blindingly gluing together fragments found who know where. I recommend you get an introductory book or tutorial instead.

Re: Word Replacing
by swampyankee (Parson) on May 31, 2007 at 14:50 UTC

    Perl (not PERL) does not, usually, loop through all the lines of the file; to make it do so see perlrun.

    I've a few questions about your post:

    • Do you really want to replace the word in binary files? Changing "GIF" to "IMG" may make a binary file unusable. Use a file test, such as -T to see if the file is text or not (note that I've found -T and -B to be less than 100% reliable on Windows, so I would be careful on any platform).
    • If you want to change every file in a directory, you will have to loop through the files, not just loop through the records in a file. My preferred way of doing this is glob to get the file names, and looping through the resulting list.
    • You can change files in place; there is a Perl runtime option to do so. See perlrun. I believe the option is -i. I tend not to use this option; when I need to change a file in situ my preference is Tie::File.
    • Just about every language with which I've dealt is case sensitive when dealing with strings; in Perl (and other languages) this can be turned off in regular expressions (regex); see perlretut
    • Depending on the size of your files, you may want to localize $/ (see perlvar) so each file's contents are read as a single string, vs reading the file line by line, e.g., something like this:
      use strict; use warnings; sub subsitute { (my $filename, my $oldword, my $newword) = @_[0..2]; local $/; if(open(my $fh, "<", $filename)){ my $contents = <$fh>; $contents =~ s/\b$oldword\b/$newword/ig; close($fh); if(open($fh, ">", $filename){ print $fh $contents; close($fh); return 1; # for success } else{ warn "Could not open $filename for writing because $!; skippin +g it\n"; return undef; } } else { warn "Could not open $filename because $!; it will be skipped\n"; return undef; } }
      I'm explicitly opening the file for writing as I don't want to assume that the -i runtime option is specified. Also, I'm assuming that case is not important and that you want every instance of $oldword replaced.

    You will have to do some more checks than just to see if the file is binary or not. Obviously, you should make sure that you've got correct rights to change the file. I would also advise that you copy the file, instead of changing it in place, until after you've thoroughly tested the code. You would, for example, not want to change source code in such a way as to introduce a syntax error or undefined external reference. And changing system("cp $oldfile $newfile"); to system("rm $oldfile $newfile"); could tend to be career inhibiting.

    emc

    Any New York City or Connecticut area jobs? I'm currently unemployed.

    There are some enterprises in which a careful disorderliness is the true method.

    —Herman Melville
      Hi, thankx for the help, BUT nothin of this is working ...

      I tryed all the examples which were mentioned here ...
      perl -pi.orig -e 's/original/substitute/g' <filename>


      or
      perl -spi -e 's/Bartholome/Richard/g' /path/to/folder/*


      The only thing what i achieved was, that my command line told me that i cant work with a file without and backoup or something like that ...

      Than even the full script, but it was full of errors, about 2-3 ...

      Guys, i know that i am like an insect but i really need help ... And you are my only hope - or i have to spend hours replacing a word by hand ... Please write me an exact way how to do that ...

      Than, if youll be in Slowakia lemme know, ill buy you a beer ... Thank you
        perl -p -i_ARCHIVE.txt -e "s/original/subst/g" <path to FILE>


        good, afrer HOURS spend on googling the net i found this one ... Its workning on MS WIN without problems ...

        It replaces the word, saves it under original form {name and file type} and creates a backup in form : original_ARCHIVE.txt ...

        Nice ... And now the last thing what i need is, how to work with more files? If i type in as path to file:

        C:/test/* - Does not work C:/test/*.* - Does not work C:/test/"*" - Does not work C:/test/"*.*" - Does not work


        And so i have NO idea hot to let him work with all files in a folder, what you told me does not work ..