|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Ok I posted earlier on how to edit flat files via http. I've figured that out now but I still have probs. This is just a trial before I add it to the main script. So I created a file called called "test.txt" with the following.
sno|name ----------- 1|shiju 2|thomas 3|rajesh 4|james Say I want to change # 3 to PETER THOMAS, all I do is I load all the contents of "test.txt" into a file called "temp.txt" unless the sno is 3. Once this is done I Load the contents of temp.txt into an array, I then basically delete all the contents of test.txt and re-print the contents of the array into the file. Once this is done I close the files ,re-open test and append the ammended record onto the end. Yes this does work, woopee I thought to myself, one prob it prints the results out to the file like so. 1|shiju 2|thomas 4|james 3|PETER THOMAS How do I get it so that it looks like 1|shiju 2|thomas 4|james 3|PETER THOMAS Here's the code incase u were wondering. Code:
#!/usr/bin/perl
open(TEMP,">temp.txt") || die "Error creating a file $!\n";
#open a temperary file for storing the data from test.txt
open(DB,"test.txt") || die "Error opening database $!\n";
#@test = <DB>;
#open test.txt file
while(<DB> ){
chomp;
($sno,$name)=split(/|/,$_);
if ($sno != "3") {print TEMP "$_\n";}
#print the records to the temp.txt except sno 3
}
#rename the temp.txt to test.txt
#now 3rd row has been deleted from the database.
close(DB);
close(TEMP);
open (TEMP,"temp.txt") || die "Error reading file $!\n";
@temp = <TEMP>;
open (DB,">test.txt") || die "Error reading file $!\n";
seek(DB,0,0);
print DB "@temp";
close(DB);
#now just appned the 3rd row to the test.txt
open(DB,">>test.txt") || die "Error open database $!n";
seek(DB,0,2);
#open database in append mode..
print DB "3|PETER THOMAS\n";
close(DB);
|
|
#2
|
|||
|
|||
|
This is just a hunch, but I think the problem starts in the original 'test.txt' that looks like this:
Code:
sno|name ----------- 1|shiju 2|thomas 3|rajesh 4|james I would check to see if there is an extra empty line after '4|james'. If there is take it out and you should be fine. The problem is that even if the line is empty the newline character counts as a 'defined' line. So when you say: Code:
while ( <DB> ) {
#code
}
the empty line gets picked up. You chomp it but then you print to the temp file '$_\n' which just puts it in again. The same thing happens then when you close and reopen the files. Try that. Hope that helps.
__________________
- dsb - ![]() Perl Guy |
|
#3
|
|||
|
|||
|
Did you try to do what I told you to do?
If that doesn't work then let me know. |
|
#4
|
|||
|
|||
|
here you are
test.txt before:
---------------- any lines here 1|linas 2|marius 3|jonas 4|darius any lines here ---------------- here is the code you need Code:
#!/usr/bin/perl
$filename = "test.txt";
$texttoreplace = "3|PETER THOMAS";
#find out whitch line to change
$texttoreplace =~ m/^([0-9]*)/; #get first digits into $1
$whitchline = $1;
#load data
open (FILE, "$filename"); @lines = <FILE>; close (FILE);
#replace
foreach (@lines){
(m/^([0-9]*)/) && ($1 eq $whitchline) && ($_ = "$texttoreplace\n");
}
#save data
open (FILE, ">$filename"); print FILE @lines; close(FILE);
test.txt after: ---------------- any lines here 1|linas 2|marius 3|PETER THOMAS 4|darius any lines here ---------------- [Edited by Sonis on 03-08-2001 at 12:03 PM] |
|
#5
|
|||
|
|||
|
Without reading anybody's replies, I can tell you 2 things that are wrong with your code:
Code:
($sno,$name)=split(/|/,$_); You need to slash out the pipe (|) because that is a character used in a regex (which is what the split command uses). Code:
if ($sno != "3") {print TEMP "$_\n";}
You can't use == or != when comparing a string value. You need to be using 'eq': Code:
if ($sno eq "3") {print TEMP "$_\n";}
I highly suggest you use the method that you set out to use in the first place and not the regex idea given to you by the others (thought they're code if functional and might work, there could be a million times the code doesn't work). If you really want to use a regex to get the 'key' of the line (number), then use one like this: Code:
$var =~ m/^(\d+)\|/; $found = $1; that will look for one or more digits (incase you get above 9, which was the major flaw with the other's code) and will look until it reaches the pipe. |
|
#6
|
|||
|
|||
|
So dsb, r u saying that every time I use \n I have chomp it? Or if I open a file to chomp, also one thing that it didn't show when I posted was that number 2 and 4 were also indented by a space or two.
|
|
#7
|
|||
|
|||
|
anything wrong with
http://forums.devshed.com//showthre...11746#post37589 ? [Edited by Sonis on 03-08-2001 at 05:16 AM] |
|
#8
|
|||
|
|||
|
Well what happens if a number starts with zero? 1-9 wont catch it. And:
foreach (@lines){ Code:
(m/^([1-9]*)/) && ($1 eq $whitchline) && ($_ = "$texttoreplace\n"); } I don't even know if this would work... you're just doing a bunch of test operators. I'm thinking that it might work because perl, by nature, will check the first two tests, and if they fail wont check the third. If the 1st 2 do pass, then it'll 'test' the third one, which will set $_ equal to that and return true -- but that's just a sloopy way of doing it IMHO. |
|
#9
|
|||
|
|||
|
yeah there should be [0-9].
with (m/^([0-9]*)/) && ($1 eq $whitchline) && ($_ = "$texttoreplace\n"); everything is fine, I need to execute 3rd condition only when first two are true. it works fine and is at least twice shorter than yours ![]() nevermind ______________ just expected thanks for that code... |
|
#10
|
|||
|
|||
|
Well I didn't even offer a solution, so it's literally impossible for yours to be short.
The only reason that your works is because of what I'd consider a bug in perl. Any other language would check all three, regardless of what the other two result in. Here's a much better method, IMO (Note: this is based off your existing 'method', I would probably approach it an entirely different way): Code:
foreach (@lines) {
chomp;
$_ = (/^$whitchline\|/) ? $texttoreplace . $/ : $_ . $/;
}
This will work every time and doesn't rely on a perl bug to work. [Edited by JonLed on 03-08-2001 at 12:29 PM] |
|
#11
|
|||
|
|||
|
JonLed,
before considering it's a bug or not, check this out in Oreilly's book "Learning Perl" Chapter 9.6 or http://www.google.com/search?q=cach...rn/ch09_06.php3 So.. my solution is not only shorter but it's also faster. Because it executes only first operator, and executes all three of them only when we need to change that line. But yours executes two(not counting chomp) for every line. (sure it would be faster if there is only one line in the file) Sonis [Edited by Sonis on 03-08-2001 at 05:30 PM] |
|
#12
|
|||
|
|||
|
Hang on
Explain these regexps to me would you, I'm still pretty new to all this. The methods which you guys are going on about would they still work from form input? I say this because to edit the record, the final version won't have a static bit to append rather it will be defined via the browser! |
|
#13
|
|||
|
|||
|
Code:
(m/^([0-9]*)/) && ($1 eq $whitchline) && ($_ = "$texttoreplace\n"); It means: find the number at the beginning(^) of the line, if you found it, check if it's equal $whitchline(we got it from $texttoreplace), if this is also True, then replace this line with $linetoreplace.. Sure it will work fine with value from form. Just add some code before. smth like.. use CGI; $mycgi = CGI::new; $texttoreplace = $mycgi->param('inputname'); Sonis ____________ just simple... [Edited by Sonis on 03-09-2001 at 02:32 PM] |
|
#14
|
|||
|
|||
|
1) You're not going to find that 'feature' (bug IMO) in any other language, so you're getting stuck on a really bad programming habit.
2) Mine would actually execute faster because it doesn't evaluate any double quotes. Yours also has too many parts (if you wanted to do it in your 'style'). You don't need the 2nd evaluation if you make the first one smarter. 3) Mine only evaluates one time (not counting chomp). Just because you don't understand the ?: syntax doesn't mean you can go around assuming things about it. As as for the chomp, is just to ensure that the lines are uniform. I understand the nature of perl, but just because perl happens to support something (as sloppy as that) doesn't mean you should get in the habit of using it. What if the person needed to do more than just change the value of a variable? Then you've gone and left this person out in the cold. |
|
#15
|
|||
|
|||
|
So If I want more than nine records I should use
Code:
$var =~ m/^(\d+)\|/; $found = $1; And not Code:
$texttoreplace =~ m/^([0-9]*)/; And with that $found = $1; whats that do? Is that some sort of flag to break out of a loop? Is this the line you guys are arguing over, I have to say I understand the second example more than the first whats (\d+) do in a regexp? Some more explanation needed please! |
![]() |
|