One Liner to reverse sort file

H

hogg

I was wondering if there was a one liner that would reverse order a
file w/o having to write the output to another file. I can reverse
order a file using: awk '{printf "%10d\t%s\n",NR,$0}' <FILE> | sort -nr
| cut -f2- >> <FILE2>, but this makes me create another file. I wanted
to be able to do it 'on the fly'.
Any suggestions?
 
W

Walter Roberson

:I was wondering if there was a one liner that would reverse order a
:file w/o having to write the output to another file.

my @revsortedfile = sort { $b cmp $a } <FILE>;
 
X

xhoster

hogg said:
I was wondering if there was a one liner that would reverse order a
file w/o having to write the output to another file. I can reverse
order a file using: awk '{printf "%10d\t%s\n",NR,$0}' <FILE> | sort -nr
| cut -f2- >> <FILE2>,

No need for all of that, at least not on modern Linux:

tac FILE > FILE2
but this makes me create another file. I wanted
to be able to do it 'on the fly'.

It does not make you create another file, that is what you chose to
do. You could certainly pipe the output into just about anything you want,
rather than redirecting it to a file.
Any suggestions?

You were so busy telling us what you didn't want to do, you failed to tell
us what you do want to do.

If you want the reversed data as input to perl, you can do:

open my $fh, "tac File |" or die $!;
while (<$fh>) {
#do whatever
}
close $fh or die $!;

If you want the reversed data written back to the same file, you could tie
the file to an array with Tie::File, and then just reverse the array. But
that would probably be ungodly slow. You could study Tie::File code and
then make your own module which does what you want quickly, and then invoke
that module with a one-liner. Come to think of it, you could just read the
file into an array, reverse the array, and print it back out, assuming the
whole file fit into memory. Leaving perl and going back to Linux, you
could do (in tcsh, doesn't seem to work in bash):

tac FILE | ( rm FILE ; cat - > FILE )

Xho
 
X

xhoster

If you want the reversed data written back to the same file, you could
tie the file to an array with Tie::File, and then just reverse the array.

Come to think of it, that would also require the whole file to be memory
at once, unless you looped through the array reversing it in place.

Xho
 
A

Ala Qumsieh

hogg said:
I was wondering if there was a one liner that would reverse order a
file w/o having to write the output to another file. I can reverse
order a file using: awk '{printf "%10d\t%s\n",NR,$0}' <FILE> | sort -nr
| cut -f2- >> <FILE2>, but this makes me create another file. I wanted
to be able to do it 'on the fly'.
Any suggestions?

Something like this?

perl -lp0 -i -e '$_ = join "\n" => reverse split /\n/' in.file

or a bit shorter:

perl -aF"\n" -lp0 -i -e '$_=join$\,reverse@F' in.file

--Ala
 
J

jl_post

Ala Qumsieh replied:
Something like this?

perl -lp0 -i -e '$_ = join "\n" => reverse split /\n/' in.file

or a bit shorter:

perl -aF"\n" -lp0 -i -e '$_=join$\,reverse@F' in.file


If I remember correctly, there was an even shorter solution given as
an answer to a problem in Randal L. Schwartz & Tom Phoenix's book
"Learning Perl":

perl -e "print reverse <>"

Quite elegant, in my opinion. :)

-- Jean-Luc Romano
 
A

Ala Qumsieh

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If I remember correctly, there was an even shorter solution given as
an answer to a problem in Randal L. Schwartz & Tom Phoenix's book
"Learning Perl":

perl -e "print reverse <>"

Quite elegant, in my opinion. :)

Except that it doesn't fulfill the OP's requirement of in-place editing
of the file.

--Ala
 
J

jl_post

hogg said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

(e-mail address removed) replied:
Ala Qumsieh replied:
Except that it doesn't fulfill the OP's requirement of
in-place editing of the file.


Oh, so in-place editing was what the original poster meant by
"without having to write the output to another file." (Before I
learned Perl, I would use sed and awk quite extensively. On occasion,
I would have to write out an intermediate file because of some logical
limitation that wouldn't let me chain awk and sed commands
indefinitely. I thought the original poster was talking about this
logical limitation. I was wondering why nobody had mentioned my
solution.)

To redeem myself, let me offer another solution, one that does what
I think the original poster wanted:

perl -pi -e 'unshift @a,$_; $_=""; print @a if eof' in.file

(I know that a solution isn't needed anymore, but I thought I might
offer yet another solution just for solution's sake.)

-- Jean-Luc
 
W

Wes Groleau

I was wondering if there was a one liner that would reverse
Oh, so in-place editing was what the original poster meant by
"without having to write the output to another file." (Before I
[snip]
To redeem myself, let me offer another solution, one that does what
I think the original poster wanted:

perl -pi -e 'unshift @a,$_; $_=""; print @a if eof' in.file

FWIW, perl in-place editing actually does write to a temporary file,
then renames it and deletes the original. Saves you the trouble of
writing explicit code for that, but that's what it does behind the
scenes. Anything that can stop you from doing it explicitly can stop
perl from doing it. (Full disk, for one example)
 
A

Arndt Jonasson

Or for those lacking tac:

% tail -r

That was a new one for me. It turns out the -r option is not available
everywhere either. HP-UX doesn't have it, for example.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top