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

I have a 30 kb "keys" file in which is readable as a text document and would probably be best suited to read as plaintext. I have three variables I assign values from a "searchfile" then i use these values to search the keys file for the right keys. In the keys file the layout is identical for every key revision... like this:

revision=something <--newline at end of line version=something <--newline at end of line type=something <--newline at end of line key1=64 characters <--newline at end of line key2=32 character <--search will stop before going to newline


In $var we will assign revision from values read from searchfile
In $var1 we will assing version from values read from searchfile
In $var2 we will assign type from values in a searchfile

Now what I am doing here is searching a "searchfile" to get the values for the variables so I can search a keys file for the correct keyset :)

Now for the question... what would be the best way to search for these three values in the key file? would a simple
if ($string =~ "$var $var1 $var2"){ seek ( $keys, 4, 0 ); read ( $keys, $temp1, 64 ); seek ( $keys, 4, 0 ); read ( $keys, $temp2, 32 );

Please understand there are newline characters after each string in the keys file. Im not sure if need to
$string =~ "$var $var1 $var2"

Or if I need to allow for the newline characters like:
$string =~ "$var\n $var1\n $var2"

Also I am not sure if doing a regex match will allow me to search the keys file from the end of the last match as per my example above. is there a way to return the very last rightmost position of the regex match?(as in the last character in the matched pattern $var2 ( type=somethin|g <-- as in last character " I need to retun the position of the very very last character g or whatever character it may be, letter or number))

EDIT

I could instead just get leftmost position of match then skip down 3 lines in the keys file. I think that would be more beneficial.

If i need to be any more specific please let me know.
Do you think this code will work for what i need?
Thanks for any input as it is appreciated :)

Replies are listed 'Best First'.
Re: searching for multiple matches and then seek from last match
by 2teez (Vicar) on Jun 09, 2014 at 09:13 UTC

    Hi james28909,

    Let me try re-frame what you are trying to do and work within that premises as your intent in this post is not clear to me. More so, probably showing the content of both searchfile and key file, and the format of how your final output will look like would have also help.

    That said, I think you want to read dataset from your searchfile into three scalar variables, then use those to search lines from another file called key file to search and get the corresponding values of the three variables. If that is right, one of the ways you can achieve your aim is like so:

    use warnings; use strict; use Inline::Files; use Data::Dumper; my %set = map { chomp; $_ => undef } <SEARCHFILE>; while (<DATA>) { if ( my ( $key, $value ) = /^(.+)=(.+)\s+</ ) { if ( exists $set{$key} ) { push @{ $set{$key} }, $value; } } } print Dumper \%set; __SEARCHFILE__ revision version type __DATA__ revision=0.0.1.1 <--newline at end of line version=0.0.1 <--newline at end of line type=A <--newline at end of line key1=64 characters <--newline at end of line key2=32 character <--search will stop before going to newline revision=0.0.2.1 <--newline at end of line version=0.0.2 <--newline at end of line type=B <--newline at end of line key1=64 characters <--newline at end of line key2=32 character <--search will stop before going to newline revision=0.0.3.1 <--newline at end of line version=0.0.3 <--newline at end of line type=C <--newline at end of line key1=64 characters <--newline at end of line key2=32 character <--search will stop before going to newline revision=0.0.4.1 <--newline at end of line

    OUTPUT:
    $VAR1 = { 'revision' => [ '0.0.1.1', '0.0.2.1', '0.0.3.1', '0.0.4.1' ], 'version' => [ '0.0.1', '0.0.2', '0.0.3' ], 'type' => [ 'A', 'B', 'C' ] };
    Note: This might not meet your need but should get you a look into what you are doing. The regex I used might also not work for you even if my premises is correct ( hope so ) You might also want to see How do I post a question effectively?.
    All I did, was to get data from searchfile as keys of an hash, then using a regex, pick out what I need from the key file, if the hash keys exists. Then display it.
    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
      well see what the problem is, is that the search file only references which key you need, it doesnt contain the actual key. and the way the keyfile is formatted i have to search specifically for 3 matches then set pos as a variable with
      $setPos = "@-" #
      and then
      seek $keysfile, $curPos, 0;
      then skip 3 lines to the actual key and read 32 characters, then goto next line and read 64 characters, and store them into $erk, and $riv.
      but i actually have got it working the way i want it, but have encountered a problem, which should be solvable easily enough...
      the same keyset is used between different file revision, so say for instance if i need a version "16" key, it could actually be a version "12" key. so now i need to add abunch of if version statements like
      if ($keyversion = "version=16"){ $keyversion = "version=12"; print $keyversion; #will print "version=12" and that lets me know it will search for +"version=12" and return the correct key/s } or if ($keyversion = "version=14"){ $keyversion = "version=12"; print $keyversion #should print "version=12"

      was really hoping i could do this without a whole lot of if statements but im manually having to search this keyfile because the original tool to read this keysfile is in C and i do not understand it lol. but its working nicely, as long as all three regex matches work.

      it searches the keys file for the expected values derived from the search file, and when it finds a match it skips three or four lines depending on the verison of the file, and then seeks to the actual key and reads 32 or 64 characters and stores them into $erk and $riv respectively.
      i know this probably sounds crazy as all get out, but it works :devilface: and it returns the correct data everytime as long as there is an exact match, and thats where the predicament comes in, because the same key is used between different version of the file for some reason :l

      also i am not very familiar with hashes. but there are different file types, different key versions, and file revisions of each file type.