2016-09-17 2 views
-2

У меня есть текстовый файл с каждой структурой линии, как это:Сортировка смешанных текстовых строк (alphanum) в Perl

P[containerVrsn:U(0)recordVrsn:U(0)size:U(212)ownGid:G[mdp:U(1090171666)**seqNo:U(81920)**]logicalDbNo:U(1)classVrsn:U(1)timeStamp:U(0)dbRecord:T[classNo:U(1064620)size:U(184)updateVersion:U(3)checksum:U(748981000) 

И должны сортировать строки файлов, основанные на SEQNO (мин макс). Номер последовательности может быть практически любым числом, начиная с нуля. Любая идея, как это можно сделать эффективным образом?

+1

Если это * одна строка * вашего входного файла, то мы не можем помочь вам его сортировать: он уже отсортирован! Пожалуйста, взгляните на [* Как я могу задать хороший вопрос? *) (Http://stackoverflow.com/questions/how-to-ask) и [* Справка по редактированию Markdown *) (http://stackoverflow.com/редактирование-помощь). Вы должны предоставить гораздо больше информации. – Borodin

ответ

2

Шварца Transform как предложено в Toto's answer, вероятно, самый быстрый способ сортировки строк здесь. Но вы сказали, что новичок в Perl, и мне нравится показывать, как можно сортировать строки традиционно.

Perl имеет sort function, который сортирует список просто по алфавиту. Но вы можете поставить пользовательскую функцию сравнения и позволить sort использовать свою функцию для сравнения элементов. Во время своей работы sort должен непрерывно сравнивать два элемента (= строки) вашего списка и решать, какой из них больше или меньше или равны ли они.

Если вы предоставляете функцию сравнения, то sort будет называть ее двумя такими элементами, как параметры $a и $b. Вам не нужно не должны объявлять $a и $b, они волшебные и просто там. Ваша функция сравнения может выглядеть следующим образом:

sub by_seqNo 
{ 
    # extract the sequence number from $a and $b 
    my ($seqA) = ($a =~ /seqNo:U\((\d+)/); 
    my ($seqB) = ($b =~ /seqNo:U\((\d+)/); 

    # numerically compare the sequence numbers (returns -1/0/+1) 
    $seqA <=> $seqB; 
} 

Первые две строки извлечь номера после seqNo:U( и сохранять их как $seqA и $seqB. Третья строка сравнивает эти порядковые номера как целые числа и возвращает результат. В сочетании с функцией sort это дает:

my @sorted = sort by_seqNo @lines; 

Причина Шварца Transform (ST) быстрее, чем это решение, потому что ST делает (дорогой) операцию извлечения SEQNO из ваших линий ровно один раз для каждой строки. С другой стороны, «традиционный» подход извлекает seqNo дважды для каждого сравнения.

+0

Спасибо за объяснение. Мне очень приятно учиться с вами, ребята, здесь. Приветствия! – Nikson

2

Вы можете использовать Schwartzian Transform.

Вот небольшой скрипт, который делает работу:

#!/usr/bin/perl 
use strict; 
use warnings; 

open my $fhi, '<', 'path/to/input/file' or die "Unable to open input file: $!"; 
my @lines = <$fhi>; 
my @sorted = map { $_->[0] } 
      sort { $a->[1] <=> $b->[1] } 
      map { my ($x) = $_ =~ /SeqNo:U\((\d+)/i; [$_, $x]; } 
      @lines; 
open my $fho, '>', 'path/to/output/file' or die "Unable to open output file: $!"; 
print $fho $_ for @sorted; 
+0

Спасибо, не могли бы вы написать его как отдельный сценарий, так как я новичок в perl – Nikson

+0

@Nikson: Смотрите мое редактирование. – Toto

+0

Спасибо, работает как шарм! – Nikson

Смежные вопросы