PHP and Sed for String Substitution

I needed to replace a string in several thousand files scattered all over the filesystem on one of our servers. I used find to create a list of files that needed to be changed, along with their complete path and called it “list.txt”. It looked something like this:


/path/to/file/one/fileone.html
/path/to/file/two/filetwo.php
/path/to/file/three/filethree.htm
/path/to/directory with spaces/filefour.txt
and so on...

I worked out the “sed” command to do the in place editing, and Zach helped me whip up a quick PHP script to read the contents of “list.txt” into an array and iterate through it. He was also nice enough to show me how to use “str_replace” to escape any annoying spaces that happened to find their way into the names of directories.

  1. < ?php
  2. $files=file('list.txt');
  3.         foreach($files as $file)
  4.         {
  5.         $command='/bin/sed -i \'s/old-string/new-string/g\' '.str_replace(' ','\ ',$file);
  6.         exec($command);
  7.         }
  8. ?>

It’s a handy little script that I’m sure I will find a use for later, so I thought I would put it up here.

Bash For loop Example

I’m always forgetting the syntax to make “for” loops in Bash. I guess it serves me right for using foreach most of my UNIX life instead. Anyhow, I know I will have to come back here to find it, so I thought I would write put up this quick example with the hope that it will be useful to others as well.

for i in $(seq 1 100); do echo -n "file${i} "; touch file${i} 2>&1; done

The the above for loop will create 100 files (called file1, file2, etc.).

Perl Lesson #1

Fun with variables:

Create a new variable with text in it and print it out.

  1. #!/usr/bin/per
  2. $textvar = "Some Text";
  3. print $textvar;

Create a new variable with a number in it and print it out.

  1. #!/usr/bin/perl
  2. $numbervar = 1;
  3. print $numbervar;

Create and increment a text variable. This will increment the letter in the variable by one alphabetical letter. For instance it will increment the letter “a” to “b”. It also understands case, which means that if you variable is an upper-case “A”, it will increment it to an upper-case “B”.

  1. #!/usr/bin/perl
  2. $lettervar = "A";
  3. $textvar ++;
  4. print $lettervar;

Create and increment a number variable.

  1. #!/usr/bin/perl
  2. $numbervar = 1;
  3. $numbervariable ++;
  4. # or
  5. $numbervar = $numbervar + 1;
  6. print $numbervar;

Create a variable with a lot of things in it, and split it up into individual variables on a “:” symbol, and print out the resulting individual variables.

  1. #!/usr/bin/perl
  2. $data = "1:2:3:4:5";
  3. ($a,$b,$c,$d,$e) = split (/:/,$data);
  4. print "$a, $b, $c, $d, $e";

Create variables with strings in them, and glue two strings together.

  1. #!/usr/bini/perl
  2. $numbervar = 1;
  3. $textvar = "String number:" . "-->" . $numbervar;
  4. print $textvar;

Perl Lesson #2

In this little script, we take the Apache access_log file, and read it into an array. Each element of the array is split on the space (” “), and we print out the first element, which is the IP address of the machine connecting to our website.

Here is the format for the log file:


69.47.145.197 - - [15/Jan/2006:22:35:12 -0500] "GET / HTTP/1.1" 301 354
69.47.145.197 - - [15/Jan/2006:22:35:39 -0500] "GET /content/images/oa1.jpg HTTP/1.1" 301 376
69.47.145.197 - - [15/Jan/2006:22:35:40 -0500] "GET / HTTP/1.1" 301 354
202.7.166.167 - - [16/Jan/2006:00:02:41 -0500] "GET /content/images/oa1.jpg HTTP/1.0" 301 376
202.7.166.167 - - [16/Jan/2006:00:06:23 -0500] "GET /content/images/oa1.jpg HTTP/1.0" 301 376
66.249.64.14 - - [16/Jan/2006:00:14:08 -0500] "GET /robots.txt HTTP/1.0" 301 364

  1. #!/usr/bin/perl
  2. open (FD, "/path/to/your/access_log");
  3. while (<fd>)
  4. {
  5. @array = split (/[" "]/);
  6. foreach $i (@array)
  7.         {
  8.         print $array[0] . "\n";
  9.         }
  10. }
  11. close (FD);

In this example we use the special variable “$_”. This is used to hold data from the file without having to do an explicit read operation. If we wanted to split the lines on other characters we could do something like this:

@array = split (/[-,:," "]/);

This would split it on the dash “-“, colon “:” and the space ” “.

If we wanted to read out each line as it is read in, we could simply replace:

print $array[0] . "\n";

With:

print $i . "\n";