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

I'm new to perl and am wondering whether there is an easy way to search through a simple text database file from the last line to the first. I want the user to determine whether to search in reverse or forward order. I seem to only be able to find instructions on how to search in ascending record order via the standard OPEN statement. Thanks in advance.

Replies are listed 'Best First'.
Re: Backwards searching
by btrott (Parson) on Jun 14, 2000 at 00:49 UTC
(jcwren) Re: Backwards searching
by jcwren (Prior) on Jun 14, 2000 at 00:52 UTC
    How large your file is affects the options you have. If the file is less than a few hundred kilobytes, it might be easiest to load the file into memory and treat it like an array.

    If your file is larger, but static, you may want to build a series of indexes that represent the byte offset of the start of each line. If the file changes with any about of frequency, however, this option would probably not be so good.

    The problem is that reading backwards in a file on a line by line basis is not a "natural" thing for most (if any) operating systems to do. Most operating systems support fairly efficient methods of moving of the file pointer around, but have no concept of "lines". Lines are an arbitrary construct, and are dependant on what you call your end of line character (typically a linefeed (unix), or carriage return/linefeed (DOS/Windows), or someother character of the user's choosing.

    While there isn't any code in this example to tell you how to do it, maybe it'll give you some ideas about how to manage the data.

    --Chris

    Update: Or better yet, use btrotts solution.
      Thanks guys for the quick response. I oversimplified by using the term "lines." If there is a way to read bytes from a file pointer position backwards--that would be a great help. If not, I do have some work-arounds I can use, but I'd like to know if it's possible.
(jcwren) RE: Backwards searching
by jcwren (Prior) on Jun 14, 2000 at 01:33 UTC
    You might want to check out the Mmap module on CPAN. It allows you to map a file into a Perl variable. As I understand it (and I've not used it) BSD & Linux allow a file to be mapped into memory. As you access various portions of the file, it basically page faults the corresponding block from the file into your user memory space. It seems that if you only access the front and end of a file, it will only load those parts, and not the remaining middle portion.

    I don't know what the speed impact of using it would be, but it might be a possible way for manipulating your data.

    I had thought this facility might be usable under Perl, so Thanks! to chromatic for telling me where the module was.

    --Chris
      HP-UX supports memory mapped files as well, although how it works with the Perl method of doing so is an exercise for the reader. (I'm not wizardly enough to try it myself right now..)
Re: Backwards searching
by Anonymous Monk on Jun 15, 2000 at 20:08 UTC
    I think that this problem could be solved recursively. Load myfile into $_. Then s/(^.*)(searchterm{1}?*$)/$1/s until all occurences of /searchterm/ are gone.