One Liner to reverse sort file

Discussion in 'Perl Misc' started by hogg, Mar 9, 2005.

  1. hogg

    hogg Guest

    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?
    hogg, Mar 9, 2005
    #1
    1. Advertising

  2. In article <>,
    hogg <> wrote:
    :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>;
    --
    "No one has the right to destroy another person's belief by
    demanding empirical evidence." -- Ann Landers
    Walter Roberson, Mar 9, 2005
    #2
    1. Advertising

  3. hogg

    Guest

    "hogg" <> wrote:
    > 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

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Mar 9, 2005
    #3
  4. hogg

    Guest

    wrote:
    >
    > 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

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Mar 9, 2005
    #4
  5. hogg

    Ala Qumsieh Guest

    hogg wrote:
    > 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
    Ala Qumsieh, Mar 10, 2005
    #5
  6. hogg

    Guest

    > hogg wrote:
    > >
    > > 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?


    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
    , Mar 10, 2005
    #6
  7. hogg

    Ala Qumsieh Guest

    wrote:

    >>hogg wrote:
    >>
    >>>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.

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

    > 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
    Ala Qumsieh, Mar 10, 2005
    #7
  8. hogg

    Guest

    > >>hogg wrote:
    > >>
    > >>>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.

    > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    replied:
    >
    > > 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 <>"


    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
    , Mar 11, 2005
    #8
  9. hogg

    Wes Groleau Guest

    >>>>>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.

    >> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    > 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)

    --
    Wes Groleau

    Armchair Activism: http://www.breakthechain.org/armchair.html
    Wes Groleau, Mar 11, 2005
    #9
  10. hogg

    Guest

    wrote:
    > "hogg" <> wrote:
    >> 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


    Or for those lacking tac:

    % tail -r

    Axel
    , Mar 14, 2005
    #10
  11. writes:
    > wrote:
    > > "hogg" <> wrote:
    > >> 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

    >
    > 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.
    Arndt Jonasson, Mar 14, 2005
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    7
    Views:
    731
    Stefan Arentz
    Sep 10, 2007
  2. Navin
    Replies:
    1
    Views:
    671
    Ken Schaefer
    Sep 9, 2003
  3. David Stanford

    File.delete one-liner

    David Stanford, Feb 3, 2009, in forum: Ruby
    Replies:
    8
    Views:
    119
    Joel VanderWerf
    Feb 5, 2009
  4. Larry
    Replies:
    1
    Views:
    94
    Martien Verbruggen
    Feb 3, 2005
  5. ahq_2001
    Replies:
    2
    Views:
    105
    Tsu Do Nimh
    May 17, 2005
Loading...

Share This Page