Grep Tricks

Often I need to mess with the content of arrays. They often look like this.

“99”, ”

And I’ll want to delete the contents of one section.


^"([0-9]*)"(,"")(,"[a-zA-Z0-9 ,-/'&#ñéá]*")
"\1"\3\2

This says, start at the beginning of each line ^, look for double quotes, then a number—repeated as many times as you want, then another double quote,

Look for any letter, number, and a bunch of special characters that don’t include double quotes “.

([a-zA-Z0-9 ,-/’&#ñéá]*)

Find all the files in a directory.

When I find a comic amusing, I grab a screenshot of it. I thought it would be nice to display one comic on my home page each day, so I wrote a little code to look in the comics directory and find all the files, then randomly choose one to display.

There are a few interesting things about the code. First up is scope. Notice that I initialized the two arrays outside of the while loop. That way when I add elements to the arrays, they are not local to the loop. Second, notice that I don’t use an index to add to the arrays. In PHP the preferred way to add an element to an array is with the $arrayName[] notation. Third, I define $location to be the directory handle of the directory. Since I assign it in an if statement, if it fails to find the directory, none of the rest of the code runs. Fourth, I use a similar pattern to read the files in the directory. I read files until there aren’t any more. Finally, I use a flag in my URL so I can proof all of the comics— $all = $_GET[‘all’];.


<?php

$title = array();
$comicsLst = array();

$title = array();
$comicsLst = array();

if ($location = opendir('./Comics')) {

    while (false !== ($entry = readdir($location))) {
   
        if ($entry != "." && $entry != "..") {

            $titleArray = explode(".", $entry);
            $title[] = $titleArray[0];
            $comicsLst[] = $entry;
        }
    }
    closedir($location);
   
    $numComics = count($comicsLst);

    $randomComic = rand(0,$numComics);

    $all  = $_GET['all'];

    if (is_null($all)) {
        echo "<p>";
        echo "<img class='align-left' src='/Comics/$comicsLst[$randomComic]' ";
        echo "alt='$title[$randomComic]' title='$title[$randomComic]' /> ";
        echo "</p>";
        /*
        echo "<p class='attribution'>";
        echo "<a href='index.php?p=Comics&all=y'>Display all comics.</a>";
        echo "</p>";
        */
    } else {

        for($i=0; $i<$numComics; $i++) {
            echo "<p>";
            echo "$title[$i]<br />";
            echo "<img class='align-left' src='/Comics/$comicsLst[$i]' alt='$title[$i]' /> ";
            echo "</p>";
        }
    }
}

I frequently find new comics and add them to my local folder. To keep them synchronized with the server, I wrote a little rsync script.


#!/bin/bash
rsync -a -H -vv -z -l --update --delete --exclude \ Comics --exclude .DS_Store ~wellgolly/Documents/Comics/ \
wellgolly@ wellgolly:/www/WellGolly/Comics/ > \
~ wellgolly/Sites/rsync-backup-comics-`date +%F`.log

Remove all the files in a directory with a specific name

I have a web app that generates temporary files as part of a shell script. The files start with ‘frequency’ and have a hash appended. Sometimes the app doesn’t clear them out. This line does it. At some point I need to put this in a cron job, but I haven’t done it yet.


sudo find /tmp -iname "frequency*" -exec rm -f {} \;

By the way, I think the reason that the files are not cleared out is that they are generated by SpamBots. The code for clearing temporary files is on the display page. It never executes because the page that displays the results is never loaded.

Things I can’t remember: More GREP goodness

When cleaning up mailing lists, I often need to remove the zip+4 info. It is usually at the end of a line so this grep works in BBEdit to find them.


-[0-9]{4}$

Look for a dash followed by the numbers 0-9 four times and then an end of line.

Working on a word list, we needed to find and delete all of the words with 1, 2, or 3 letters. So we use this code switching out the 1 for 2 and 3. Note the ^ and $. This means that we start at the beginning of the line look for the pattern and nothing else until the end of the line.


^[a-zA-Z]{1}$

We could use the same technique to find all of the words with more than 5 letters, but then we’d have to do a bunch of searches. Instead we used this.


[a-zA-Z]{5}[a-zA-Z]

Here we look for pattern of five letters and then look for one more. Not to belabor the point, but suppose together is in the word list. It has five letters, toget and one more h. It also happens to have some more letters after that, but we don’t particularly care. We just care that there are more than 5.