Kittu
Kittu

Reputation: 43

perl : how to sort lines in a file depending on the second field and update the same file

file : entries.txt

d1 t-waaa.html
a1 t-paaa.html
e1 t-waaa.html
c1 t-uaaa.html
b1 t-paaa.html
f1 t-paaa.html

perl file check.pl

#! /bin/perl
$cur_file = $ARGV[0];  # here ARGV[0] is entries.txt
open (FILE, "< $cur_file") or die "cannot open file: $!";
@file_lines = <FILE>;

@lines = map $_->[1],
         sort { $a->[1] <=> $b->[1] }
         map { my ($num) = /-\s*(\d+)/; [ $num, $_ ] } @file_lines;

print @lines;

i'm not getting the expected output. file is getting printed as it is.

expected output :

a1 t-paaa.html
b1 t-paaa.html
f1 t-paaa.html
c1 t-uaaa.html
d1 t-waaa.html
e1 t-waaa.html

where the code went wrong, i'm no sure.

Upvotes: 0

Views: 92

Answers (3)

amit bhosale
amit bhosale

Reputation: 482

Above mentioned code is good. you can also use package use List::UtilsBy 'sort_by'; please check https://metacpan.org/pod/List::UtilsBy

use strict;
use warnings;
use List::UtilsBy 'sort_by';
use Data::Printer;

my $cur_file =   "entries.txt";
open (FILE, "< $cur_file") or die "cannot open file: $!";
my @file_lines = <FILE>;
close(FILE);

my @lines = sort_by { (split(' ', $_))[1] } @file_lines;
p @lines;

Output

perl sort.pl
[
    [0] "a1 t-paaa.html
",
    [1] "b1 t-paaa.html
",
    [2] "f1 t-paaa.html",
    [3] "c1 t-uaaa.html
",
    [4] "d1 t-waaa.html
",
    [5] "e1 t-waaa.html
"
]

Upvotes: 1

Dada
Dada

Reputation: 6626

  • \d matches a digit; you probably wanted to use \w, or \S or [a-z] instead.

  • <=> compares numbers; you don't have numbers to compare but string. Use cmp instead.

  • The second elements (->[1]) of your arrays contain the file names rather than the fields you want to compare. Use ->[0] instead.

Overall, that gives you:

@lines = map $_->[1],
         sort { $a->[0] cmp $b->[0] }
         map { my ($num) = /\s+(\S+)/; [ $num, $_ ] } @file_lines;

Note that I've replaced -\s* by \s+ since the title of your question mentions that you want to sort according to the second field, which seems to occur after a white-space character. Feel free to use -\s* if needed.

Upvotes: 4

vkk05
vkk05

Reputation: 3222

Since its a string compression, your code should look like this:

...
@lines = map $_->[1],
         sort { $a->[1] cmp $b->[1] }
         map { my ($num) = /-\s*(\d+)/; [ $num, $_ ] } @file_lines;
...

Upvotes: 0

Related Questions