Closed Thread Icon

Preserved Topic: Global Find & Replace using find & perl. Pages that link to <a href="https://ozoneasylum.com/backlink?for=21001" title="Pages that link to Preserved Topic: Global Find &amp;amp; Replace using find &amp;amp; perl." rel="nofollow" >Preserved Topic: Global Find &amp; Replace using find &amp; perl.\

 
Author Thread
jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-06-2001 17:19

Okay, I am basically a Perl newbie, and not much better than that w/ shell utilities. I could look this up on my own, but if someone could just post a one-liner for me on how the syntax should look it would save me a lot of time and prevent my site from looking like crap for the next few hours . I just want to replace the regexp:

<link rel="stylesheet" href="((../)*coffman.css)">

w/

<link rel="stylesheet" href="\1">\n<style type="text/css">\n<!--\n@import "\2coffman2.css";\n-->\n</style>

in all .html files under a certain directory.

I imagine my find command will look something like:

find /home/httpd/html -iregex .*\.html

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-06-2001 19:38

http://www.meybohm.de/os/rxr.html

Also, note that back references should be written with dollar sign not slash (i.e. "$1").

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-06-2001 20:56

Thanks. That script is actually decipherable. I suppose it's time I picked up a Perl book... I keep reading that it's easier than C and Java both of which I have a very good understanding of.

-jiblet

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-06-2001 21:03

Yep, PERL is easy...

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-06-2001 22:06

Okay, I made a modification to that script so that I could filter out files that already have the change I am attempting to make... before I run it, if you would check it out to make sure I didn't make any big mistakes that are gonna fry my data I would appreciate it...

code:
@files=<stdin>;
foreach $file (@files) {
print "Processing ";
print $file;
chop $file;
if (-e $file) {
open(INPUT, "<$file");
@text=<INPUT>;
close (INPUT);
foreach $row (@text) { //I added this foreach
if ($row=~/$notcontaining/i) {
$leavealone = 1;
}
}
if (!$leavealone) { //and this if statement.
foreach $row (@text) {
$row=~s/$searchfor/$replacewith/ixg;
}
open(OUTPUT, ">$file");
print OUTPUT @text;
close(OUTPUT);
}
$leavealone = 0;
} else {
print "File does not exist! Skipping...\n";
$error++;
}
}



-jiblet

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-06-2001 22:52

That looks fine to me. But, don't blame me if something goes wrong, heh...

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-06-2001 22:56

eheheh, of course not. The worst that could happen is I do a rm -r * in which case I would simply re-upload all my files

Actually I was kind of hoping you would say something like "Well, that WORKS, but it would be much more efficient if you did it like this: (crazy perl one-liner with 10 operators I've never seen before)"

-jiblet

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-06-2001 23:35

He he he. Actually, I wanted to suggest that you break out from your foreach loop in the if statement that you've added, because there's no reason to go through when you set $leavealone to true (it would save a few CPU cycles), but then again if it ain't broke, don't fix it... BTW The command that will break out from loop in PERL is "last()"...



[This message has been edited by mr.maX (edited 07-06-2001).]

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-06-2001 23:48

Okay, there's one last problem. How do I format the arguments?

The examples given are somewhat ambiguous because my regexps contain spaces. So can I put each argument in double quotes then escape double quotes? Or do I just escape spaces? Here's the command that I got to run, but it apparently didn't match the regexps I wanted because the files remained unchanged:

<BLOCKQUOTE><FONT face="Verdana, Arial">code:</font><HR><pre>
find /home/coffman/html/ -iregex .*\.html

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-07-2001 15:36

I don't have enough time to analyze what you've done, so for the sake of simplicity, I hardcoded all things directly in script, so that you don't have to call it with arguments. Also, I've fixed your regular expressions (you forgot to escape some things, like ".").

#!/usr/bin/perl

$error=0;
@files=<stdin>;
foreach $file (@files) {
&nbsp;&nbsp;&nbsp;&nbsp;print "Processing $file";
&nbsp;&nbsp;&nbsp;&nbsp;chop $file;
&nbsp;&nbsp;&nbsp;&nbsp;if (-e $file) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open(INPUT, "<$file"); @text=<INPUT>; close(INPUT);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$leavealone = 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach $row (@text) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($row=~/\@import/i) { $leavealone = 1; last;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!$leavealone) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach $row (@text) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$row=~s/<link rel="stylesheet" href="((\.\.\/)*coffman\.css)">/<link rel="stylesheet" href="$1">\n<style type="text\/css">\n<!--\n\@import "$2coffman2.css";\n-->\n<\/style>/ig;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;open(OUTPUT, ">$file"); print OUTPUT @text; close(OUTPUT);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$error++;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print "File does not exist! Skipping...\n";&nbsp;&nbsp;&nbsp;&nbsp;$error++;
&nbsp;&nbsp;&nbsp;&nbsp;}
}
if ($error > 0) {
&nbsp;&nbsp;&nbsp;&nbsp;print "Finished with $error errors!\n";
}

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-09-2001 17:19

Wow, yeah, figuring out what to escape is kind of a bitch eh? I suppose passing arguments makes it even more complicated. Anyway, thanks again, I'm going to have to print out some kind of reference for this... perhaps man perlre

-jiblet

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-09-2001 21:50

Actually, passing arguments isn't the most complicated thing here. It's the script, because it would have to be changed in order for the backreferences to work properly...

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-10-2001 22:35

Is that because it interprets $ literally when it's contained within a variable? If so, would backslash backreferences not work in this case?

-jiblet

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-10-2001 22:52

In this particular script, practically nothing will be interpreted. Take "\n" character for example (it will be written literally like that, there would be no new line).

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-11-2001 19:22

Hmmm, so in other words the script is totally useless for searching for regular expressions which is its goal...

-jiblet

mr.maX
Maniac (V) Mad Scientist

From: Belgrade, Serbia
Insane since: Sep 2000

posted posted 07-11-2001 19:36

Well, you can use limited regular expressions as search string, but you can't use backreferences and other similar stuff as replace string.

Anyway, I don't know what was the real goal of this script, because I didn't create it, heh...

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-11-2001 21:37

No Max, that's impossible, you can't not know!!!!

::head explodes::

-jiblet

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-12-2001 19:37

hey, now I have yet another problem. Say I want to replace a 5 line block with 1 line, what approach should I use? Obviously the script I'm using here replaces line by line, so I need to search the whole file in one regexp. Do I have to concatenate the rows together or can I just refer to the @text array directly? Also I suppose I will need the s modifier to treat it as a single line to be searched.

-jiblet

rob
Nervous Wreck (II) Inmate

From:
Insane since: Apr 2000

posted posted 07-12-2001 20:10

perl -pi.bak -e s/foo/bar/gs `find . -name *.html -print`

will replace all accurrences of foo with bar for all files named *.html in the current directory *and below.* Those are backticks around the find command. Now delete that POS perl script.


[This message has been edited by rob (edited 07-12-2001).]

jiblet
Paranoid (IV) Inmate

From: Minneapolis, MN, USA
Insane since: May 2000

posted posted 07-12-2001 22:32

Hmm, your find syntax didn't work on my linux, it doesn't let me exclude files based on regex matches, and it doesn't give any feedback to what it's doing. So somehow it doesn't seem to make up for the POS script.

Tweaking your one-liner would be more work than just figuring out how to put a whole file through a regexp substitution, which I have been trying to find in the perl docs, but it's hard to find specific things like that which is why I asked here.

-jiblet

« BackwardsOnwards »

Show Forum Drop Down Menu