tmbailey123 has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone, I am looking for a script that sorts lines in a hosts file.
Some lines have "#" comments appended to the end of the line
describing the type of machine, location or application and
I really need to keep that info in the file. Here is a brief
sample of what I am dealing with.

One other thing I only have to sort one class C subnet,
therefore the sort can be isolated to the 4th octet.

<code> 10.194.196.46 chqnocp01 # Laser 4MV by Joe Blow
10.194.196.47 chqnocp02
10.194.196.49 nnocrpt01
10.194.196.50 nnocgw001
10.194.196.52 nnocs002
10.194.196.53 wslkms02 wslknms0
10.194.196.54 nnocws001
10.194.196.55 heckyll
10.194.196.57 txwl013w
10.194.196.61 krios
10.194.196.62 stasis # dial up server
10.194.196.63 nnocdts01 # sparc 5 in wan rm
10.194.196.64 saturn
10.194.196.65 libra
10.194.196.66 legato-school
10.194.196.67 txwlxdbs nnocs002a
<code>

thx

-mike

Replies are listed 'Best First'.
Re: sorting /etc/hosts
by thraxil (Prior) on Aug 31, 2001 at 22:25 UTC

    probably don't need perl. there's a shell command that can do this.

    % man sort

    so the whole thing might go something like:

    sort -n /etc/hosts > /tmp/hosts.sorted mv /tmp/hosts.sorted /etc/hosts

    anders pearson

Re: sorting /etc/hosts
by tachyon (Chancellor) on Aug 31, 2001 at 23:11 UTC

    If you must do it in Perl use the Schwartzian Transform for efficiency. This avoids finding the 4th octet more than once for each line and is thus fast(er) than it might otherwise be.

    my @unsorted = <DATA>; my @sorted = map{ $_->[0] } sort{ $a->[1] <=> $b->[1] } map { [$_, get_fourth($_) ] } @unsorted; sub get_fourth { local $_ = shift; /\d+\.\d+\.\d+\.(\d+)/; return $1; } print "@sorted"; __DATA__ 10.194.196.55 heckyll 10.194.196.57 txwl013w 10.194.196.61 krios 10.194.196.62 stasis # dial up server 10.194.196.63 nnocdts01 # sparc 5 in wan rm 10.194.196.65 libra 10.194.196.66 legato-school 10.194.196.67 txwlxdbs nnocs002a 10.194.196.46 chqnocp01 # Laser 4MV by Joe Blow 10.194.196.47 chqnocp02 10.194.196.49 nnocrpt01 10.194.196.64 saturn 10.194.196.50 nnocgw001 10.194.196.52 nnocs002 10.194.196.53 wslkms02 wslknms0 10.194.196.54 nnocws001

    Update

    Changed order to ascending numrical order as per spec (I think)

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Using Unix sort
by Rhose (Priest) on Aug 31, 2001 at 22:35 UTC
    As posted above, I would use the Unix sort -- fields are delimited with a dot, and you want to numerically sort on the 4th field.
    sort -t. +3n /etc/hosts
    Does that work for you?
      excuse me I replied to the wrong reply. yes

      sort -t +3n /etc/hosts

      works !

      thx again

      -mike

      Yes, I tried a sort -n but, here is a snippet of my output.

      <code> 10.194.196.10 romulus
      10.194.196.100 nnocws014
      10.194.196.101 wslkms01 wslknms01
      10.194.196.102 nnocws016
      10.194.196.103 nnocws017
      10.194.196.104 txwl008w
      10.194.196.105 nnocws019
      10.194.196.106 txwl015w
      10.194.196.11 otter
      10.194.196.110 nnocweb01
      10.194.196.111 shemp
      10.194.196.113 dvwl000s
      10.194.196.125 spanky
      10.194.196.126 buckwheat
      10.194.196.127 datapro
      10.194.196.128 darla
      10.194.196.129 txwl018w
      10.194.196.13 nnocdev01
      <code>

      this is not what we are looking for.

      kind regards

      -mike

Re: sorting /etc/hosts (boo)
by boo_radley (Parson) on Aug 31, 2001 at 22:38 UTC
    Is this a trick?

    updated to compensate for my foolish assumption.

    use strict; my @lines=<DATA>; print sort{by_ip($a)<=>by_ip($b)} @lines; sub by_ip { @_[0]=~ /\.(\d+)\s/; return $1; } __DATA__ 10.194.196.55 heckyll 10.194.196.57 txwl013w 10.194.196.61 krios 10.194.196.62 stasis # dial up server 10.194.196.63 nnocdts01 # sparc 5 in wan rm 10.194.196.65 libra 10.194.196.66 legato-school 10.194.196.67 txwlxdbs nnocs002a 10.194.196.46 chqnocp01 # Laser 4MV by Joe Blow 10.194.196.47 chqnocp02 10.194.196.9 TEST 10.194.196.49 nnocrpt01 10.194.196.64 saturn 10.194.196.50 nnocgw001 10.194.196.52 nnocs002 10.194.196.53 wslkms02 wslknms0 10.194.196.54 nnocws001
      Your example sorts lexically, not numerically. It'll sort 10.10.10.10 before 10.10.10.2, for example:
      my @lines=<DATA>; print sort @lines; __DATA__ 10.194.196.9 made-up 10.194.196.55 heckyll 10.194.196.57 txwl013w 10.194.196.61 krios 10.194.196.62 stasis # dial up server
      This sorts the "made-up" line to the end, whereas the original poster presumably would want it first.

      Like the other replies said, a numerical sort is more appropriate here. The number of "cycles" used either way is going to be pretty trivial.

      add to your DATA: 10.194.196.9 nnocws001 10.194.196.100 nnocws001 and you'll see it's not quite so straight-forward. you're doing a sort based on "standard string comparison order", instead of numerical. though the OP doesn't specify.