This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Problem with deleting a whole line of a textfile

Help for those learning Tcl or writing their own scripts.
Post Reply
d
darton
Op
Posts: 155
Joined: Sat Jan 21, 2006 11:03 am

Problem with deleting a whole line of a textfile

Post by darton »

Hello!
In the meantime I have managed many things with eggdrop <-> textfiles. But with deleting a line out of a textfile I have a problem. You can see my script here:

Code: Select all

bind pub - !delop delop
proc delop {nick uhost hand chan arg} {
global adminfile
 if {$arg != ""} {
  set op [lindex [split $arg] 0] 
  set fd [open $::adminfile r+]
      while {![eof $fd]} {
         lappend list [gets $fd]         
      }          
     if {[set le [lsearch -exact $list $op]] != -1} {
          #The following line should do the delete stuff, but doesn't
          set list [lreplace $list $le $le]
          puts -nonewline $fd [join $list \n]
          close $fd
        } else {
          putquick "PRIVMSG $chan :Your moderator does not exist."
        }
 } 
}
According to the "Basic File Operations" Thread of stdragon a line should be deleted by the following code: "set lines [lreplace $lines $line_to_delete $line_to_delete]". De_Kus said to me that the variable $list and $lines are equivalent. With the line "[set le [lsearch -exact $list $op]]" I am looking for the name $op in the textfile and I am saving the line into the variable $le. So $le and $line_to_delete should be the same, too. But it does not work. The content in the textfile is simply copied and pasted again.
Can anybody tell me where the mistake is?
Last edited by darton on Fri Aug 11, 2006 11:56 am, edited 1 time in total.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

$lines and $list are not the same...
lreplace can't alter $list, as it only sees it as variable content, rather than the variable itself. Basically, you could use it without variable aswell, ie:

Code: Select all

set mylist [lreplace [list a b c d e] 3 4]
Try something like this:

Code: Select all

bind pub - !delop delop
proc delop {nick uhost hand chan arg} {
 global adminfile
 if {$arg != ""} {
  set op [lindex [split $arg] 0]
  set fd [open $::adminfile r+]
  while {![eof $fd]} {
   lappend list [gets $fd]         
  }         
  if {[set le [lsearch -exact $list $op]] != -1} {
   puts -nonewline $fd [join [lreplace $list $le $le] \n]
   close $fd
  } else {
   putquick "PRIVMSG $chan :Your moderator does not exist."
  }
 }
}
NML_375
d
darton
Op
Posts: 155
Joined: Sat Jan 21, 2006 11:03 am

Post by darton »

Exactly the same happens. Another suggestion?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Actually, when you open the file with r+, any writes to the file will append the new data, ie. the file is not truncated pre-write..
close it after you've read it, and open it with w+ when you wish to write to it..

Code: Select all

bind pub - !delop delop
proc delop {nick uhost hand chan arg} {
 global adminfile
 if {$arg != ""} {
  set op [lindex [split $arg] 0]
  set fd [open $::adminfile r+]
  while {![eof $fd]} {
   lappend list [gets $fd]         
  }
  close $fd
  set fd [open $::adminfile w+]
  if {[set le [lsearch -exact $list $op]] != -1} {
   puts -nonewline $fd [join [lreplace $list $le $le] \n]
  } else {
   putquick "PRIVMSG $chan :Your moderator does not exist."
  }
  close $fd
 }
} 
NML_375
d
darton
Op
Posts: 155
Joined: Sat Jan 21, 2006 11:03 am

Post by darton »

It works perfectly now. Thank you.
d
darton
Op
Posts: 155
Joined: Sat Jan 21, 2006 11:03 am

Post by darton »

By the way, is it possible to delete more than one line?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Yep.
If the lines are consecutive, just alter the "last"-argument of lreplace, and it'll replace all elements between "first" and "last" (inclusive).

If the lines are spread out however, you'll have to use multiple lreplace's.
In this case I'd suggest you'd rewrite the script slightly in order to store the result from each lreplace in a variable inbetween the lreplace operations..
ie:

Code: Select all

set dellist [list "lines" "to" "be" "removed"]
...
foreach op $dellist {
 if {[set le [lsearch -exact $list $op]] != -1} {
  set list [lreplace $list $le $le]
 }
}
puts -nonewline $fd [join $list "\n"]
Oh, a word of advice, there is a chance that your file will be cleared if you try to remove a line that's not in the file in the example I wrote earlier (my bad). A simple solution would be to only open and close the file a second time if the lsearch is successful (just move the open and close-command inside the if-statement)

Code: Select all

  if {[set le [lsearch -exact $list $op]] != -1} {
   set fd [open $::adminfile w+]
   puts -nonewline $fd [join [lreplace $list $le $le] \n]
   close $fd
  } else {
   putquick "PRIVMSG $chan :Your moderator does not exist."
  }
NML_375
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

I've said that countless times before, but darton just won't listen.

The (arguably) proper way of using files in eggdrop scripts is:
  • open the file only ONCE, on script's start-up; read the entire content into a list (or array or whatever), then close the file
  • manipulate that list as you wish in your event handlers
  • periodically SAVE the list into file
I've yet to see an eggdrop script having to handle files so large that the above won't work
connection, sharing, dcc problems? click <here>
before asking for scripting help, read <this>
use

Code: Select all

 tag when posting logs, code
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

I'd guess that'd be the only way of doing it, unless you'd like to mess with temp-files..
Oh well, there is random-access mode, but unless you're comfortable coding fixed-size datastructures with lazy-delete, you really don't wanna touch that one ;)
NML_375
d
darton
Op
Posts: 155
Joined: Sat Jan 21, 2006 11:03 am

Post by darton »

demond wrote:I've said that countless times before, but darton just won't listen.
I am not good in making proper scripts. My scripts work but aren't proper.:wink:

But the script above is proper, isn't it?
Post Reply