http://qs321.pair.com?node_id=11101394


in reply to Re^4: Sort alphabetically from file
in thread Sort alphabetically from file

Also, if your on Windows like me, I open($file, '<', shift) or die "$!"; and then immediately binmode($file);.

Commands or parameters or filenames added to the command line when calling the script get put into an array called @ARGV and when you call shift it increments $ARGV[0] to $ARGV[1] to $ARGV[2] and so on for each shift used.

So, if you used C:\path\to\script\perl my_script.pl file_1.txt outfile.txt then you could use shift again to open() (use three arg open) and instead of printing it to the console window, you can write the output to $outFile.

use strict; use warnings; my %hash; open (my $inFile, '<', shift) or die "$!"; open (my $outFile, '>', shift) or die "$!"; binmode($inFile); binmode($outFile); while (<$inFile> =~ /(\d)\s+(\d)\s+(\d)\s+(\w+)/){ push @{$hash{$4}}, $1, $2, $3; } print $outFile "@{$hash{$_}}[0..2] $_\n" for sort keys %hash;
Usage: C:\path\to\script\perl my_script.pl inFile.txt outFile.txt

Also, please note this also removes one space from each column per row. As long as that does not corrupt your data set it should be fine. It actually may save you some hard drive space. :)

EDITED: fixed typo in matching patterns, thanks haukex

EDITED: changed and made obvious that the individual needs to make absolutely certain that this does not corrupt anything in their data set.

EDITED: had to add a new paragraph so my second EDIT looked ok.

Replies are listed 'Best First'.
Re^6: Sort alphabetically from file
by haukex (Archbishop) on Jun 16, 2019 at 09:11 UTC
    when you call shift it increments $ARGV[0] to $ARGV[1] to $ARGV[2] and so on for each shift used.

    No, shift removes the first element of @ARGV on each call, returning the element it removed.

    /(\d)\s*(\d)\s*(\d)\s*(\w*)/

    Note that this will also match a line as simple as "123", or really anything that has three consecutive digits, since that's the only thing this regex requires. I would strongly recommend using \s+, \d+, and \w+, and anchoring the regex to the beginning and end of the string with ^ resp. $.

    As long as that does not corrupt your data set it should be fine (and i am sure it is fine)

    Sorry, but how can you be sure? Some file formats require \t as a column separator.

    Update: Expanded the last quote and highlighted the part I was reacting to.

      No, shift removes the first element of @ARGV on each call, returning the element it removed.

      so shift physically removes the entry in @ARGV? this is interesting and i did not realize that. also thanks for pointing out the problem there, i actually did some reading on matching myself, and was trying some new stuff and forgot to change it back to how it was, so i will go back and change that right now. thanks.

      the provided sample data was not '\t'. as far as i can tell it was not tab separated. it was a double space. there is no reason under the sun (that i can think of) to have two white spaces between data, actually spaces between data is kind of flawed in itself really, your better off using a comma or some other separator that is not normally used. anyways, the same regex would match both cases as well. if you want to pick that apart thenyoull have a blast if go further down in the comments below and find the person who matched two words in different columns. that would throw off your data quicker than removing a white space.

      EDIT: you also took what i said out of context for the most part, what i said was: As long as that does not corrupt your data set it should be fine (and i am sure it is fine)

        so shift physically removes the entry in @ARGV? this is interesting and i did not realize that

        Indeed it does:

        $ cat shifter.pl #!/usr/bin/env perl use strict; use warnings; do { print "ARGV is @ARGV\n"; print "Shifting " . shift . " off ...\n"; } until $#ARGV < 0; $ ./shifter.pl x y z ARGV is x y z Shifting x off ... ARGV is y z Shifting y off ... ARGV is z Shifting z off ... $

        See perldoc -f shift for more.

        the provided sample data was not '\t'. as far as i can tell it was not tab separated. it was a double space. there is no reason under the sun (that i can think of) to have two white spaces between data

        Well, even if you can't think of a reason, the OP's file format appears to use it ;-) The main point here is this: we don't know the OP's real file format. Depending on where the source code was copied-and-pasted from, tabs could have been converted to spaces. The data is so simplistic that it most likely isn't the real data the OP is working with. And if it is, then it's most likely a homework assignment, and if I was an instructor, in my next assignment I might specifically design my input file format to allow for single whitespace characters in a column and require two or more whitespace characters between columns, just to teach people about how to handle strange situations like that. People tend to get pretty creative in their file formats.

        spaces between data is kind of flawed in itself really, your better off using a comma or some other separator that is not normally used

        I absolutely agree!

        you also took what i said out of context for the most part, what i said was: As long as that does not corrupt your data set it should be fine (and i am sure it is fine)

        If it had just been the first part of the sentence, without the part in parentheses, then I think it's a great way to word it. But the part in parentheses expresses a level of certainty that we just can't have. Even re-reading the sentence now, I don't see another way to understand the wording of that sentence; if I'm mistaken, please feel free to explain what you meant. I quoted that part because that's what I was objecting to, plus a little more so the quote would make more sense. And if someone was missing context, your post is still there :-) I've updated my post though.

        To put it a different way: It sounded like you were saying not to worry about it, but not thinking about these kinds of issues is what contributes to people designing some "strange" file formats :-)

        In such cases I find it better to ask the OP to be specific about their file format (providing a hex dump if necessary), to design a solution as robust and defensively coded as possible based on the data given (i.e. it rejects data that isn't exactly like the sample data), and/or to provide a solution but explain all of the assumptions and limitations.

        By the way, it looks like you've edited your post without mentioning the edit. Please see How do I change/delete my post?, in particular "It is uncool to update a node in a way that renders replies confusing or meaningless".