Link to home
Start Free TrialLog in
Avatar of ItsMe
ItsMe

asked on

change entrys in plain text database

Hi !
I have got a plain text database of the following structure:

item1|item2|item3
item1|item2|item3
item1|item2|item3
item1|item2|item3

and so on.
What is the most easy way to change lets say item2 in line 1 to "changeditem2" ?

I want to do this with Perl. Moreover the way of modifying the db must be very secure, I don't want to lose datas. It is possible that more than 1 person accesses the db at the same time.

regards
ItsMe
Avatar of ozo
ozo
Flag of United States of America image

use Fcntl ':flock'; # import LOCK_* constants
open LOCK,">>file.lock" or die "Can't open file.lock because $!";
flock LOCK,LOCK_EX;
{local $^I=".bak"; local @ARGV=("database.txt");
  while( <> ){
    s/item2/changeditem2/ if $. == 1;
    print;
  }
}
close LOCK;
Avatar of ItsMe
ItsMe

ASKER

Hi ozo ! Thank you ! can you explain what the code above is doing and perhaps write it as a sub procedure ?
I need to access the Items by their position because it is possible that some items have the same value in the same line.

I would prefer:
sub changeitem(Line,ItemNo,NewValue);

Oh, and how must I write the use line ?
I already have

use LWP::Simple;

How can I add Fcntl to tis ?

regards
Itsme
try this.........


====================change_item.db
Manesh|Rao|27
Frank|Williams|34
Bill|Gates|36
Jerry|Bolder|45
Louisa|Walkins|65

==================change_item.pl
#!/usr/local/bin/perl

use Fcntl ':flock'; # import LOCK_* constants

$db_file="/home/webuser/manesh/tmp/change_item.db";

open LOCK,">>file.lock" or die "Can't open file.lock because $!";
flock LOCK,LOCK_EX;
{
  local $^I=".bak";
  local @ARGV=($db_file);
  print changeitem(4,2,"Bolder");
}
close LOCK;

##  Line number of the record in the file
##  Item no = column number of the | delimited record. Starting with 1
##  New Value = value to be put in that column
sub changeitem(){
  my($Line,$ItemNo,$NewValue)=@_;
  my($records,$columns,@new_rec,@columns,$rec_num);

  open(DB,$db_file) || die $!;

  $/="";
  my($db)=<DB>; ##  Read the Entire file at a go
  $/="\n";
  close(DB);

  my(@db)=split(/\n/,$db);

  $records=scalar(@db); ##  Get the total # of records

  if ($Line>$records){
    print "DB has only $records records\n";
    return 0;
  }

  foreach($[ .. $#db){
    $rec_num=$_+1;
    @columns=split(/\|/,$db[$_]); ##  Split each record
    $columns=scalar @columns; ##  Get the total columns for the record
    if ($ItemNo>$columns){
      print "DB has only $columns columns\/Items\n";
      return 0;
    }

    if ($rec_num == $Line){ ##  matching line found
      $columns[($ItemNo-1)]=$NewValue;  ##  Replace the item with new value
      $db[$_]=join('|',@columns);
    }
    push(@new_rec,$db[$_]);
  }

  open(DB,">$db_file") || die $!;
  foreach(@new_rec){
    print DB $_."\n";
  }
  close(DB);

  return 1;
}
. and keep in mind that flock() is not NFS-proofen :-(
Avatar of ItsMe

ASKER

can you explain me what flock is ?
flock() tells the UNIX kernel that we want to arrange some sort of
shared or exclusive access (in this case, exclusive) to a particular open file. If a
file is ``flocked'' exclusively, and a second process comes along wanting the
same, it gets blocked until the process with the flock releases it (by closing the
file, calling flock() again with the proper parameter, or simply exiting).


more info at

http://www.stonehenge.com/merlyn/WebTechniques/col04.html
Avatar of ItsMe

ASKER

Thanks ! I'll try it in a few days !
Avatar of ItsMe

ASKER

Thanks, is it possible to not use the line parameter but an key:

key1|blabla|blabla...
key2|blabla|blabla...
key3|blabla|blabla...
key4|blabla|blabla...

so instead of change (0,0,'test') I would like to use change ('key1',0,'test'). I tried to get this but it doesn't work. perhaps you could modify the script ?

thanks
ItsMe
would the key be unique??
if yes,i would be able to give you the modified ver. fast.

Rgds
Avatar of ItsMe

ASKER

yes. each key is unique.
ASKER CERTIFIED SOLUTION
Avatar of maneshr
maneshr

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ItsMe

ASKER

Thank you very much !
I'll try it when I wake up tomorrow :-)
What does this do: ?

open LOCK,">>file.lock" or die "Can't open file.lock because $!";
flock LOCK,LOCK_EX;
{
  local $^I=".bak";
  local @ARGV=($db_file);
  #print changeitem(4,2,"Bolder");
  print changeitem("Key1",3,"Bolder");
}
close LOCK;

I'm relatively new in Perl. I don't know what the meaning of ^? is...
Guten nacht!!
Avatar of ItsMe

ASKER

Danke schön.

Cool ! Where are u from ?

i bin aus Indien, aber i kann ein bischen deutsch.
Avatar of ItsMe

ASKER

thanx !