Reading a file backwards

Reading a file backwards

Post by Tom Krotchk » Wed, 25 Jul 2001 20:58:36



Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
any will work for me.
 
 
 

Reading a file backwards

Post by Ian P. Springe » Wed, 25 Jul 2001 21:52:02


Quote:> Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> any will work for me.

Do you mean line-by-line backwards, or character-by-character?

 
 
 

Reading a file backwards

Post by Tom Krotchk » Wed, 25 Jul 2001 22:10:55


On Tue, 24 Jul 2001 12:52:02 GMT, "Ian P. Springer"


>> Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
>> any will work for me.

>Do you mean line-by-line backwards, or character-by-character?

line by line backwards.
 
 
 

Reading a file backwards

Post by Ben.Altma » Wed, 25 Jul 2001 22:53:58



> On Tue, 24 Jul 2001 12:52:02 GMT, "Ian P. Springer"

> >> Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> >> any will work for me.

> >Do you mean line-by-line backwards, or character-by-character?
> line by line backwards.

Here are 3 ways:
1. Get the length of the file and use sed going backwards line by line (sed
-n ${line}p $file).  To speed things up you could buffer several lines at a
time.
2. Without the length of the file you could do a tail -n$line | head -n1,
increasing $line until you get to the start of the file (you could also
buffer this).
3. If the file isn't too big you might be able to to load it all into an aray
using awk and then print out the array backwards.
 
 
 

Reading a file backwards

Post by Ashok Aiy » Wed, 25 Jul 2001 23:05:33


On Tue, 24 Jul 2001 09:10:55 -0400,

> On Tue, 24 Jul 2001 12:52:02 GMT, "Ian P. Springer"

>>> Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
>>> any will work for me.

>>Do you mean line-by-line backwards, or character-by-character?
> line by line backwards.

How about using `tac`?  It is part of the GNU textutils package.  From
the tac.1 manpage:

TAC(1)                                                     TAC(1)

NAME
       tac - concatenate and print files in reverse

Later,
Ashok
--

Department of Microbiology-Immunology           office: (312) 503-2524
303 E. Chicago Avenue, WARD 4-123                  lab: (312) 503-2542
Northwestern University, Chicago, IL 60611         fax: (312) 503-1339

 
 
 

Reading a file backwards

Post by Tom Krotchk » Thu, 26 Jul 2001 00:23:13


Thanks all, you've given me the clue I'm looking for.
 
 
 

Reading a file backwards

Post by Matthew Land » Thu, 26 Jul 2001 00:35:12



> Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> any will work for me.

How about `tail -r <filename>`.  Is that simple enough?

 - matt
--
_______________________________________________________________________

   << Comments, views, and opinions are mine alone, not IBM's. >>

 
 
 

Reading a file backwards

Post by Ben.Altma » Thu, 26 Jul 2001 02:51:49




> > Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> > any will work for me.

> How about `tail -r <filename>`.  Is that simple enough?

That's useful to have.  Unfortunately not on HP UX though ):
 
 
 

Reading a file backwards

Post by Matthew Land » Thu, 26 Jul 2001 04:31:28





> > > Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> > > any will work for me.

> > How about `tail -r <filename>`.  Is that simple enough?

> That's useful to have.  Unfortunately not on HP UX though ):

Ok, here is another option.  Not sure how fast it is compared to
other methods, but seems quick to me.  Also doesn't require knowing
the line number or parsing line by line.

 cat -n /etc/rc.net |sort -r |sed 's/^[ ]*[0-9]*     //'
                                       ^        ^^^^^
                                     space       tab

 - Matt

--
_______________________________________________________________________

   << Comments, views, and opinions are mine alone, not IBM's. >>

 
 
 

Reading a file backwards

Post by Chris F.A. Johnso » Thu, 26 Jul 2001 05:17:53



> On Tue, 24 Jul 2001 12:52:02 GMT, "Ian P. Springer"

> >> Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> >> any will work for me.

> >Do you mean line-by-line backwards, or character-by-character?
> line by line backwards.

tac filename ## 'tac' is a GNU utility.

As a shell script, this should work (accepts stdin as well as files):

cat $* | {
    IFS=""
    read f
    while read line
    do
        f="$line
$f"
    done
    echo "$f"

Quote:}

It will be quicker with awk:

cat $* | awk '
    BEGIN {getline f}
    {f = $0 "\n" f}
    END {print f}
    '

--
    Chris F.A. Johnson                        http://cfaj.freeshell.org
    ===================================================================
    My code (if any) in this post is copyright 2001, Chris F.A. Johnson
    and may be copied under the terms of the GNU General Public License

 
 
 

Reading a file backwards

Post by Ben.Altma » Thu, 26 Jul 2001 05:38:34






> > > > Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> > > > any will work for me.

> > > How about `tail -r <filename>`.  Is that simple enough?

> > That's useful to have.  Unfortunately not on HP UX though ):

> Ok, here is another option.  Not sure how fast it is compared to
> other methods, but seems quick to me.  Also doesn't require knowing
> the line number or parsing line by line.

>  cat -n /etc/rc.net |sort -r |sed 's/^[ ]*[0-9]*     //'
>                                        ^        ^^^^^
>                                      space       tab

And another good use of cat.
 
 
 

Reading a file backwards

Post by Ben.Altma » Thu, 26 Jul 2001 05:37:33






> > > > Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> > > > any will work for me.

> > > How about `tail -r <filename>`.  Is that simple enough?

> > That's useful to have.  Unfortunately not on HP UX though ):

> Ok, here is another option.  Not sure how fast it is compared to
> other methods, but seems quick to me.  Also doesn't require knowing
> the line number or parsing line by line.

>  cat -n /etc/rc.net |sort -r |sed 's/^[ ]*[0-9]*     //'
>                                        ^        ^^^^^
>                                      space       tab

That is a good idea!
 
 
 

Reading a file backwards

Post by Bill Marcu » Thu, 26 Jul 2001 06:05:04



>Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
>any will work for me.

In some versions of Unix there is a command called 'tac'.  Otherwise
you might try something like this (this reverses the lines in a file;
reversing the characters is a little more work):

awk '{lines[NR]=$0} END{for(x=NR;x>0;x--)print lines[x]}' filename

 
 
 

Reading a file backwards

Post by Ian P. Springe » Thu, 26 Jul 2001 11:05:26


Quote:> >> Is there a simple way to do this in a shell script?   Korn, Bash, CSH,
> >> any will work for me.

> >Do you mean line-by-line backwards, or character-by-character?
> line by line backwards.

I compiled the following list of solutions to this question a while back.
It's a bit HP-UX-specific, but mostly generic...

These are roughly arranged from most to least portable:

# This method is POSIX.2 portable and works on large files, and is

# also faster than using awk or sed:

pr -nt | sort -nr | cut -f2-

# Most implementations of awk can handle bigger files than sed.

# Note: On HP-UX 11, awk aborts if the input file contains any lines

# longer than 3000 characters. Method A below is considerably faster

# than method B:

awk '{l[NR]=$0} END{for (i=NR;i;i--) print l[i]}' # method A

awk '{x=$0"\n"x} END{ORS="";print x}' # method B

# Just be aware that most seds will *on big files using the

# below methods (in older ones the limit can be as small as 4k,

# and even POSIX.2 requires only 8k). On HP-UX 11.00, sed

# dumps core on files >2k (or >4k w/ sed cumulative patch PHCO_22760

# installed). The same exact bug exists in Solaris 7. sed is also

# much slower than awk. Method A below is about 33% faster than

# method B or C:

sed -n 'x;1!H;${g;p;}' # method A

sed -n '1!G;h;$p' # method B

sed '1!G;h;$!d' # method C

# nl is part of XPG2-4, but not POSIX; works fine w/ large files, and it

# is very fast:

nl -ba -w9 | sort -nr | cut -f2-

# in HP-UX 10.00 and later, Perl 4 is included (/usr/contrib/bin/perl);

# Perl imposes no limit on the size of the input file, and it is extremely

# fast:

perl -e 'print reverse <>'

# tac is part of the GNU textutils package, which does not come w/ HP-UX,

# but should come with many versions of Linux & BSD, as well as Solaris 8;

# it is both the least portable, and speediest, way to perform the task:

tac