Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to unread a line

186 views
Skip to first unread message

David Ferrington

unread,
Mar 10, 1994, 11:23:33 AM3/10/94
to
Hi all,

how do I unread a line being read from a file?

ie: given
$/ = "\nFrom ";
$rest = <FILE>;

the last characters of $rest will be ".....\nFrom "
and i'd like to put the "From " back onto the input stack as it were
I guess this is possible, but how.
What i actually want to do is read the rest of a email message until the next
message.

-----------------------------------------------------------------------------
David J Ferrington One reason why computers can do more
Customer Services & Support work than people is that they never
Sybase (UK) Limited have to stop and answer the phone!
Sybase House
Bell Street
Maidenhead
Berkshire
SL6 1XW
England Email: David.Fe...@Sybase.Com
-----------------------------------------------------------------------------
The opinions expressed are my own and not necessarily those of my employer.
-----------------------------------------------------------------------------
-D

Larry Wall

unread,
Mar 14, 1994, 12:05:31 PM3/14/94
to
In article <CMGIv...@sybase.com> David.Fe...@Sybase.Com writes:
: Hi all,

:
: how do I unread a line being read from a file?
:
: ie: given
: $/ = "\nFrom ";
: $rest = <FILE>;
:
: the last characters of $rest will be ".....\nFrom "
: and i'd like to put the "From " back onto the input stack as it were
: I guess this is possible, but how.

If you're reading from a file, seek(FILE, -6, 1) should work. If you're
reading from a pipe, it won't. There is no "unget" built into Perl, and
I've never even used the feature in C. I abominate it slightly.

Larry

Tom Christiansen

unread,
Mar 14, 1994, 1:59:42 PM3/14/94
to
:-> In comp.lang.perl, David.Fe...@Sybase.Com writes:
:Hi all,

:
:how do I unread a line being read from a file?
:
:ie: given
: $/ = "\nFrom ";
: $rest = <FILE>;
:
:the last characters of $rest will be ".....\nFrom "
:and i'd like to put the "From " back onto the input stack as it were
:I guess this is possible, but how.
:What i actually want to do is read the rest of a email message until the next
:message.

While I think you should probably find a better way to do it, I once wrote
this as an exercise. I found it to be more complex than I thought it would
be, mostly due to the interaction of putting and getting both lines and
characters from the same filehandle.

-tom

package pushback;

# Functions:
# &open(FH, path) like regular open
# &close(FH) like regular close
#
# &getline(FH) like <FH>
# &getc(FH) like getc(FH)
#
# &ungetline(FH,list) puts list of lines back in LIFO order
# &ungetc(FH,string) prepends string to next gotten line
#
# &flushin(FH) clears FH's pushback buffer
# &eof(FH) is pushback empty AND real eof?


# PACKAGE "GLOBALS" (In Capital Letters)
# 1) Each filehandle in any package has an array @pushback'${package}_${fh}__lines
# containing the pushback buffer.
#
# 2) @PB_Lines is an alias for that per-filehandle buffer
#
# 3) %Ungotten is indexed by filehandle and tells us whether
# there are pushed back chars (rather than lines)

sub main'getline {
local($fh, *PB_Lines) = &getputback;

# shouldn't have to check wantarray here -- it should know better
if (!@PB_Lines) {
if (wantarray) {
local(@list);
return @list = <$fh>;
} else {
return scalar <$fh>;
}
}

if (!wantarray) {
if ($Ungotten{$fh}) {
$Ungotten{$fh} = 0;
return pop(@PB_Lines).<$fh>;
}
return pop @PB_Lines;
}

if ($Ungotten{$fh}) {
$PB_Lines[0] .= <$fh>;
$Ungotten{$fh} = 0;
}

local(@rlist) = reverse(@PB_Lines);
@PB_Lines = ();
push(@rlist, <$fh>);
return @rlist;
}

sub main'ungetline {
local($fh, *PB_Lines) = &getputback;
if ($Ungotten{$fh}) {
$PB_Lines[0] .= shift;
$Ungotten{$fh} = 0;
}
push(@PB_Lines,reverse @_) if @_;
}

sub main'getc {
local($fh, *PB_Lines) = &getputback;
local($char);

if (@PB_Lines) {
$char = substr($PB_Lines[0], 0, 1);
$Ungotten{$fh}--;
substr($PB_Lines[0], 0, 1) = '';
} else {
$char = getc($fh);
}
return $char;
}

sub main'ungetc {
local($fh, *PB_Lines) = &getputback;
local($char) = $_[0];
$Ungotten{$fh} += length($char) unless @PB_Lines;
substr($PB_Lines[0], 0, 0) = $char;
}


sub main'eof {
local($fh, *PB_Lines) = &getputback;
@PB_Lines == 0 && eof($fh);
}

sub main'open {
local($fh, *PB_Lines) = &getputback;
local($path) = shift;
@PB_Lines = ();
open($fh, $path);
}

sub main'close {
local($fh, *PB_Lines) = &getputback;
@PB_Lines = ();
close($fh);
}

sub main'flushin {
local($fh, *PB_Lines) = &getputback;
local(@buf) = @PB_Lines;
@PB_Lines = ();
return @buf;
}

sub getputback {
local($myfh) = shift || STDIN;
local($package) = caller(1); # my grandparent
local($ptrnam) = $myfh;
$ptrnam =~ s/^[^']+$/$package'$&/;
$ptrnam =~ s/'/_/;
return ($myfh, "pushback'${ptrnam}__lines");
}

# make some aliases just in case...

*main'ungetchar = *main'ungetc;
*main'getchar = *main'getc;

1;
--
Tom Christiansen tch...@cs.colorado.edu
"Will Hack Perl for Fine Food and Fun"
Boulder Colorado 303-444-3212

Brian Johnsen

unread,
Mar 14, 1994, 4:57:32 PM3/14/94
to
In article <CMGIv...@sybase.com>,

David Ferrington <David.Fe...@Sybase.Com> wrote:
>Hi all,
>how do I unread a line being read from a file?
>ie: given
> $/ = "\nFrom ";
> $rest = <FILE>;
>the last characters of $rest will be ".....\nFrom "
>and i'd like to put the "From " back onto the input stack as it were
>I guess this is possible, but how.

Would
$rest = "From" . <FILE>;
work?
--
Brian C. Johnsen bcj...@resds2.ca.boeing.com
The Boeing Co. does not always agree with my opinions.

Chaim Frenkel

unread,
Mar 14, 1994, 10:41:39 PM3/14/94
to
Larry Wall writes:

Dems fightin' words :-)

What don't you use: unget() or seek()? Why is it an abomination and
what do you replace it with.

<chaim>
--
Chaim Frenkel On contract at:
ch...@nlk.com ch...@fsrg.bear.com
Nonlinear Knowledge, Inc. Bear Stearns & Co., Inc.

Larry Wall

unread,
Mar 16, 1994, 2:17:23 PM3/16/94
to
In article <1994Mar16....@netlabs.com> I wrote:
: Mind you, since none of those problems are helped by not using ungetc(),
: it's irrational of me to avoid using it. Nevertheless, I don't.

Heh. I just found six places where I use ungetc() in perl. I guess
I'm not as irrational as I thought I was. Or wasn't. Whatever.

Larry

Dov Grobgeld

unread,
Mar 18, 1994, 5:38:25 AM3/18/94
to
tch...@cs.Colorado.EDU (Tom Christiansen) writes:
: While I think you should probably find a better way to do it, I once wrote

: this as an exercise. I found it to be more complex than I thought it would
: be, mostly due to the interaction of putting and getting both lines and
: characters from the same filehandle.
:
: -tom
[package pushback deleted]

I'm often using the following much simpler and more limited (but usually
sufficient solution).

In a while loop reading from a file IN do

while($_ = shift(@linestack) || <IN>) {
:
push(@linestack, $whatever); # unread
}

: Tom Christiansen tch...@cs.colorado.edu


: "Will Hack Perl for Fine Food and Fun"
: Boulder Colorado 303-444-3212

--
___ ___
/ o \ o \
Dov Grobgeld ( o o ) o |
The Weizmann Institute of Science, Israel \ o /o o /
"Where the tree of wisdom carries oranges" | | | |
_| |_ _| |_

0 new messages