For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > November 2007 > How to append a file accordingly?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author How to append a file accordingly?
Why Tea

2007-11-25, 10:07 pm

How to append to a text file based on the following conditions:
1) if the last characters of the file are "\n" or "\r\n", simply
print FH "$some_text";
2) if the last characters are none of "\n" or "\r" or "\r\n", do
print FH "\n$some_text";

/Why Tea
Petr Vileta

2007-11-25, 10:07 pm

Why Tea wrote:
> How to append to a text file based on the following conditions:
> 1) if the last characters of the file are "\n" or "\r\n", simply
> print FH "$some_text";
> 2) if the last characters are none of "\n" or "\r" or "\r\n", do
> print FH "\n$some_text";
>
> /Why Tea


Maybe this way?

if($some_text =~ m/(\r\n|\n|\r)$/s)
{
print FH "$some_text";
}
else
{
print FH "\n$some_text";
}

--
Petr
Skype: callto://fidokomik
Na mail uvedeny v headeru zpravy nema cenu nic posilat, konci to v PR*
:-)

Odpovidejte na petr na practisoft cz


Petr Vileta, Czech republic
(My server rejects all messages from Yahoo and Hotmail. Send me your
mail from another non-spammer site please.)

Please reply to <petr AT practisoft DOT cz>

Why Tea

2007-11-26, 4:13 am

On Nov 26, 1:46 pm, "Petr Vileta" <sto...@practisoft.cz> wrote:
> Why Tea wrote:
>
>
> Maybe this way?
>
> if($some_text =~ m/(\r\n|\n|\r)$/s)
> {
> print FH "$some_text";
> }
> else
> {
> print FH "\n$some_text";
> }
>


Petr, your code checks for white spaces at the end of $some_text, but
I was talking about white spaces at the end of the opened file, i.e.
open(FH, $some_file)


Spiros Denaxas

2007-11-26, 4:13 am

On Nov 26, 5:26 am, Why Tea <ytl...@gmail.com> wrote:
> On Nov 26, 1:46 pm, "Petr Vileta" <sto...@practisoft.cz> wrote:
>
>
>
>
>
>
>
> Petr, your code checks for white spaces at the end of $some_text, but
> I was talking about white spaces at the end of the opened file, i.e.
> open(FH, $some_file)


Why Tea,

I believe Petr's solution involves slurping the file and then
checking.
You could use:

File::Slurp http://search.cpan.org/perldoc?Perl6::Slurp
Perl6::Slurp http://search.cpan.org/perldoc?File::Slurp

How big is the file? I believe this is a crucial factor since
for very long and/or large files, the majority of common methods
might not be applicable.

Spiros
Peter Makholm

2007-11-26, 8:07 am

Why Tea <ytlim1@gmail.com> writes:

> How to append to a text file based on the following conditions:
> 1) if the last characters of the file are "\n" or "\r\n", simply
> print FH "$some_text";
> 2) if the last characters are none of "\n" or "\r" or "\r\n", do
> print FH "\n$some_text";


Untested and without error handling:

use Fcntl qw(:s);

my $last;
open my $fh, '+<', $filename;
s $fh, -1, SEEK_END;
read $fh, $last, 1;
s $fh, 0, SEEK_END; # Probably not needed.

print {$fh} "\n" unless $last eq "\n";
print {$fh} $some_text;
Tad McClellan

2007-11-26, 8:07 am

Petr Vileta <stoupa@practisoft.cz> wrote:

> if($some_text =~ m/(\r\n|\n|\r)$/s)

^
^

the m//s modifier is a no-op for that regex.

You should not use modifiers that do not do any modification...


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
Abigail

2007-11-26, 7:13 pm

_
Tad McClellan (tadmc@seesig.invalid) wrote on VCC September MCMXCIII in
<URL:news:slrnfkkjrg.env.tadmc@tadmc30.sbcglobal.net>:
:) Petr Vileta <stoupa@practisoft.cz> wrote:
:)
:) > if($some_text =~ m/(\r\n|\n|\r)$/s)
:) ^
:) the m//s modifier is a no-op for that regex.
:)
:) You should not use modifiers that do not do any modification...


Hmmmpf.


Although I don't necessarely disagree with you, I don't think such
posts are useful. What might be useful is a reasoning why you think
you shouldn't do so. Preferably also with reasons why people (Damian
for instance, in PBP) do think you should.

I seldomly use /s, /m or /x when it's not needed, but I won't held it
against people that do.


And, given that 5.10 is just around the corner, I'd write the code as:

if ($some_text =~ /\R$/)


Abigail
--
package Just_another_Perl_Hacker; sub print {($_=$_[0])=~ s/_/ /g;
print } sub __PACKAGE__ { &
print ( __PACKAGE__)} &
__PACKAGE__
( )
Petr Vileta

2007-11-26, 7:13 pm

Why Tea wrote:
> On Nov 26, 1:46 pm, "Petr Vileta" <sto...@practisoft.cz> wrote:
>
> Petr, your code checks for white spaces at the end of $some_text, but
> I was talking about white spaces at the end of the opened file, i.e.
> open(FH, $some_file)


I assumed that whole file content is in $some_text. When you can read file
line by line then you can use this

open FH "< $myfile";
binmode FH; # not need for *nix systems
s FH, -2, 2; # s for last 2 bytes
my $lastchars = <FH>;
close FH;
open FH "< $myfile";
while (my $row = <FH> )
{
print $row;
}
close FH;
print "\n" unless($lastchars =~ m/(\r\n|\n|\r)$/s)
--
Petr
Skype: callto://fidokomik
Na mail uvedeny v headeru zpravy nema cenu nic posilat, konci to v PR*
:-)

Odpovidejte na petr na practisoft cz


Petr Vileta, Czech republic
(My server rejects all messages from Yahoo and Hotmail. Send me your
mail from another non-spammer site please.)

Please reply to <petr AT practisoft DOT cz>

Why Tea

2007-11-26, 7:13 pm

On Nov 27, 3:41 am, "Petr Vileta" <sto...@practisoft.cz> wrote:
> Why Tea wrote:
>
>
>
>
> I assumed that whole file content is in $some_text. When you can read file
> line by line then you can use this
>
> open FH "< $myfile";
> binmode FH; # not need for *nix systems
> s FH, -2, 2; # s for last 2 bytes
> my $lastchars = <FH>;
> close FH;
> open FH "< $myfile";
> while (my $row = <FH> )
> {
> print $row;
> }
> close FH;
> print "\n" unless($lastchars =~ m/(\r\n|\n|\r)$/s)
> --


Thanks Petr. The code works fine in detecting \r\n|\n|\r, but it fails
when the $lastchars are just normal characters. What I did was to
append a line of text to the file and I didn't want to have a blank
line if there is already \r\n|\n|\r. I ran your code once, it was OK
but the subsequent runs failed (I expected \n to be printed, but it
didn't).

/Why Tea
Ben Morrow

2007-11-26, 7:13 pm


Quoth Why Tea <ytlim1@gmail.com>:
> On Nov 27, 3:41 am, "Petr Vileta" <sto...@practisoft.cz> wrote:

Use three-arg open.
Use lexical filehandles.
Check the open succeeded.
[color=darkred]

Yes, it is *always* needed as of 5.8. You can also combine this step
with the open:

open my $FH, '<:raw', $myfile
or die "can't read '$myfile': $!";
[color=darkred]

Don't use magic numbers for s. Use the proper constants: it's
clearer, and safer if you ever port the code to a machine where SEEK_END
isn't 2 (such things do happen: GNU Hurd, for instance, has O_RDONLY
defined as 1 rather than 0).

use Fcntl qw/:s/;

s $FH, -2, SEEK_END;
[color=darkred]

Why do this? It just introduces an entirely unnecessary race condition,
and you haven't reopened it in binary mode, which may or may not be
important. If you wish to reinstate CRLF processing, you can say

binmode $FH, ':crlf';
[color=darkred]

It's not clear the OP wants to copy the file. If he wants to append, it
would be better to open in '+<' mode s to the end before writing.
[color=darkred]

While I'm usually a fan of using regexes rather than more low-level
solutions, this is more complicated than necessary. Something like

s $FH, -1, SEEK_END;
or die "can't s '$myfile': $!";
read $FH, my $eol, 1
or die "can't read from '$myfile': $!";

s $FH, 0, SEEK_END;
print $FH "\n" unless $eol =~ tr/\r\n//;

would be simpler. If you want to insert a newline matching the rest of
the file, you would need to read at least two characters, of course. For
normalizing newlines see PerlIO::eol.

Note also that "\r" and "\n" are not portable. Some systems have "\r" eq
"\012" and "\n" eq "\015". If you mean an ASCII CR say "\015".
[color=darkred]
> Thanks Petr. The code works fine in detecting \r\n|\n|\r, but it fails
> when the $lastchars are just normal characters. What I did was to
> append a line of text to the file and I didn't want to have a blank
> line if there is already \r\n|\n|\r. I ran your code once, it was OK
> but the subsequent runs failed (I expected \n to be printed, but it
> didn't).


It works for me here. Please post a complete script that shows how it
fails.

Note that text files *should* end with a trailing newline (in the
appropriate local format). If you have files that don't, they're
arguably broken, and you're better off fixing them than propagating the
error.

Ben

Tad McClellan

2007-11-26, 7:13 pm

Abigail <abigail@abigail.be> wrote:
> _
> Tad McClellan (tadmc@seesig.invalid) wrote on VCC September MCMXCIII in
><URL:news:slrnfkkjrg.env.tadmc@tadmc30.sbcglobal.net>:
>:) Petr Vileta <stoupa@practisoft.cz> wrote:
>:)
>:) > if($some_text =~ m/(\r\n|\n|\r)$/s)
>:) ^
>:) the m//s modifier is a no-op for that regex.
>:)
>:) You should not use modifiers that do not do any modification...
>
>
> Hmmmpf.
>
>
> Although I don't necessarely disagree with you, I don't think such
> posts are useful. What might be useful is a reasoning why you think
> you shouldn't do so.



My folks often told me "look both ways before you cross the street"
without explaining why I should.


A modifier says "something out of the ordinary is going on here".

Modifiers that don't modify are "crying wolf" to the maintenance programmer.


> Preferably also with reasons why people (Damian
> for instance, in PBP) do think you should.



I don't really remember why he said to use m//msx, but I think it was
"because they will be enabled by default in Perl 6", ie. to get
yourself ready for Perl 6.

I'll learn Perl 6 when there _is_ a Perl 6 , but while maintaining
Perl 5 code, I'm not going to cry wolf.

(I only have "buy in" for about 80% of the PBP recommendations anyway.)


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
Why Tea

2007-11-26, 7:13 pm

> It works for me here. Please post a complete script that shows how it
> fails.
>


Sorry, I made a mistake. Petr's code actually works. And your code
works fine too, Ben.

Another question, how do you extract the last line of a text file
quickly?

/Why Tea

Jim Gibson

2007-11-26, 10:08 pm

In article
<ed1f0548-c465-433a-9842-0287106ba768@d21g2000prf.googlegroups.com>,
Why Tea <ytlim1@gmail.com> wrote:

>
> Sorry, I made a mistake. Petr's code actually works. And your code
> works fine too, Ben.
>
> Another question, how do you extract the last line of a text file
> quickly?


Check out File::ReadBackwards:

<http://search.cpan.org/~uri/File-Re...eadBackwards.pm>

--
Jim Gibson

Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
xhoster@gmail.com

2007-11-27, 4:25 am

Tad McClellan <tadmc@seesig.invalid> wrote:
> Abigail <abigail@abigail.be> wrote:
>
> My folks often told me "look both ways before you cross the street"
> without explaining why I should.
>
> A modifier says "something out of the ordinary is going on here".
>
> Modifiers that don't modify are "crying wolf" to the maintenance
> programmer.


On the other hand, you could argue that /sm *is* ordinary, and their
removal is the mark of the unusual. If that is the standard to which the
maintenance programmer is accustomed, than their unwarranted absence would
be what is calling wolf, not their unwarranted presence. Sure, it would
have been nice if Perl had inverted their meanings in the first place, so
that the usual would be shorter than the unusual, but should we be
prisoners to a design flaw when we can just learn a new custom instead?

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
Abigail

2007-11-27, 4:25 am

_
Tad McClellan (tadmc@seesig.invalid) wrote on VCCI September MCMXCIII in
<URL:news:slrnfkmpd4.uml.tadmc@tadmc30.sbcglobal.net>:
:) Abigail <abigail@abigail.be> wrote:
:) > _
:) > Tad McClellan (tadmc@seesig.invalid) wrote on VCC September MCMXCIII in
:) ><URL:news:slrnfkkjrg.env.tadmc@tadmc30.sbcglobal.net>:
:) >:) Petr Vileta <stoupa@practisoft.cz> wrote:
:) >:)
:) >:) > if($some_text =~ m/(\r\n|\n|\r)$/s)
:) >:) ^
:) >:) the m//s modifier is a no-op for that regex.
:) >:)
:) >:) You should not use modifiers that do not do any modification...
:) >
:) >
:) > Hmmmpf.
:) >
:) >
:) > Although I don't necessarely disagree with you, I don't think such
:) > posts are useful. What might be useful is a reasoning why you think
:) > you shouldn't do so.
:)
:)
:) My folks often told me "look both ways before you cross the street"
:) without explaining why I should.
:)
:)
:) A modifier says "something out of the ordinary is going on here".
:)
:) Modifiers that don't modify are "crying wolf" to the maintenance programmer.
:)
:)
:) > Preferably also with reasons why people (Damian
:) > for instance, in PBP) do think you should.
:)
:)
:) I don't really remember why he said to use m//msx, but I think it was
:) "because they will be enabled by default in Perl 6", ie. to get
:) yourself ready for Perl 6.

No, that's not the reason. They are by default enabled in Perl6 because
the people developing Perl6 think it's a good idea to have them enabled
by default (and no way to easily turn them off). And for the same reasons
they are on in Perl6, Damian advocates to use them - and to make it easier
for the maintainance programmer, he advocates to turn them always on (that
way, when you see an unescaped '.', '^', '$', '#' or ' ' in a regexp, it
always means the same thing).

I don't buy your argument, and I don't by Damians either. Anyone who
considers /s or /m to be an alarm, or loses track when sometimes /s is
used, and sometimes isn't, shouldn't program Perl in the first place.



Abigail
--
perl -wle 'sub _ "Just another Perl Hacker"; print prototype q ^_^'
sheinrich@my-deja.com

2007-11-27, 8:05 am

On Nov 27, 8:39 am, Abigail <abig...@abigail.be> wrote:
....
>
> No, that's not the reason. They are by default enabled in Perl6 because
> the people developing Perl6 think it's a good idea to have them enabled
> by default (and no way to easily turn them off). And for the same reasons
> they are on in Perl6, Damian advocates to use them - and to make it easier
> for the maintainance programmer, he advocates to turn them always on (that
> way, when you see an unescaped '.', '^', '$', '#' or ' ' in a regexp, it
> always means the same thing).
>
> I don't buy your argument, and I don't by Damians either. Anyone who
> considers /s or /m to be an alarm, or loses track when sometimes /s is
> used, and sometimes isn't, shouldn't program Perl in the first place.
>
> Abigail
> --

While I share your point of view on the usage of modifiers, I'm afraid
that the outspoken 'perl-enabled' folk's snobbish attitude might be
cause for people feeling rebuffed and for the language's slowly ebbing
popularity.

TIMTOWTDI

Cheers,
Steffen

Petr Vileta

2007-11-27, 8:05 am

Ben Morrow wrote:
> Quoth Why Tea <ytlim1@gmail.com>:
>
> Use three-arg open.
> Use lexical filehandles.
> Check the open succeeded.
>
>
> Yes, it is *always* needed as of 5.8. You can also combine this step
> with the open:
>

Maybe you are right, I don't know. I'm old-fashioned, I still write scripts
for (and using) Perl 5.6.1 :-)
--
Petr Vileta, Czech republic
(My server rejects all messages from Yahoo and Hotmail. Send me your
mail from another non-spammer site please.)

Please reply to <petr AT practisoft DOT cz>

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com