perl sort 질문입니다.

lovethecorners의 이미지

다음과 같이 생성된 text 파일이 있습니다.

"11236","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-12-2006",""
"9333","Damon Delamar","Frank Troutman","Closed & Ready","6-7-2006",""
"13398","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-8-2006",""
"3497","Natalee Hengst-White","William Gonzalez","Closed & Ready","6-13-2006",""
"31957","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-9-2006",""
"32547","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-8-2006",""
"17118","Rhonda Henry","Lisa DeFazio","Closed & Ready","6-6-2006",""
"24101","Rhonda Henry","Steve Welling","Closed & Ready","6-8-2006",""
"18826","Damon Delamar","Vivian Chien","Closed & Ready","6-27-2006",""
"20442","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-27-2006",""
"33567","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-22-2006",""
"33568","Natalee Hengst-White","Frank Troutman","Closed & Ready","6-15-2006",""
"6931","Rhonda Henry","Jessica Shrode","Closed & Ready","6-15-2006",""

두번째의 컬럼은 이름입니다. 여기서 last name을 이용해 다시 정리하고 싶습니다. 어떤 방법이 있는지 알려 주시면 감사하겠습니다.

결과값은 다음과 같이 정리 하려고 합니다.

"11236","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-12-2006",""
"9333","Damon Delamar","Frank Troutman","Closed & Ready","6-7-2006",""
"18826","Damon Delamar","Vivian Chien","Closed & Ready","6-27-2006",""
"20442","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-27-2006",""
"13398","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-8-2006",""
"3497","Natalee Hengst-White","William Gonzalez","Closed & Ready","6-13-2006",""
"31957","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-9-2006",""
"32547","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-8-2006",""
"33567","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-22-2006",""
"33568","Natalee Hengst-White","Frank Troutman","Closed & Ready","6-15-2006",""
"17118","Rhonda Henry","Lisa DeFazio","Closed & Ready","6-6-2006",""
"24101","Rhonda Henry","Steve Welling","Closed & Ready","6-8-2006",""
"6931","Rhonda Henry","Jessica Shrode","Closed & Ready","6-15-2006",""

googling의 이미지

결과값의 정렬기준이 좀 애매하네요.

원하신다면 이런 방법도 있겠습니다.
위 text 를 some.txt 로 저장한다음
$ sort -k 2 some.txt

결과값은 다음과 같습니다.
"9333","Damon Delamar","Frank Troutman","Closed & Ready","6-7-2006",""
"11236","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-12-2006",""
"20442","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-27-2006",""
"18826","Damon Delamar","Vivian Chien","Closed & Ready","6-27-2006",""
"33568","Natalee Hengst-White","Frank Troutman","Closed & Ready","6-15-2006",""
"13398","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-8-2006",""
"31957","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-9-2006",""
"33567","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-22-2006",""
"32547","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-8-2006",""
"3497","Natalee Hengst-White","William Gonzalez","Closed & Ready","6-13-2006",""
"6931","Rhonda Henry","Jessica Shrode","Closed & Ready","6-15-2006",""
"17118","Rhonda Henry","Lisa DeFazio","Closed & Ready","6-6-2006",""
"24101","Rhonda Henry","Steve Welling","Closed & Ready","6-8-2006",""

aero의 이미지

일단 데이터 txt파일을 보니 CSV파일 포멧이군요.
CSV를 parsing하고 그걸 sort하는 코드를 reinvent wheel 할 필요없이

perl의 DB 프로그래밍 인터페이스인 DBI가 CSV format지원하는걸 이용해서
하시면 됩니다.
우선 DBD::CSV (DBI driver for CSV files) 모듈 부터 설치하시고 나서
데이터 파일을 표준 CSV format에 맞게 고치고 난후 작업을 하셔야 하는데
CSV파일의 맨 첫줄은 각 필드를 나타내는 필드명을 넣어주어야 합니다.
따라서 다음처럼 고치고 (필드명은 제가 임의로 넣었습니다.)

sort_list.txt

"A","B","C","D","E","F"
"11236","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-12-2006",""
"9333","Damon Delamar","Frank Troutman","Closed & Ready","6-7-2006",""
"13398","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-8-2006",""
"3497","Natalee Hengst-White","William Gonzalez","Closed & Ready","6-13-2006",""
"31957","Natalee Hengst-White","Lisa DeFazio","Closed & Ready","6-9-2006",""
"32547","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-8-2006",""
"17118","Rhonda Henry","Lisa DeFazio","Closed & Ready","6-6-2006",""
"24101","Rhonda Henry","Steve Welling","Closed & Ready","6-8-2006",""
"18826","Damon Delamar","Vivian Chien","Closed & Ready","6-27-2006",""
"20442","Damon Delamar","Rita Zdaneviciute","Closed & Ready","6-27-2006",""
"33567","Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready","6-22-2006",""
"33568","Natalee Hengst-White","Frank Troutman","Closed & Ready","6-15-2006",""
"6931","Rhonda Henry","Jessica Shrode","Closed & Ready","6-15-2006",""

다음처럼 하시면 CSV파일에 대한 일반적인 DB Query를 사용가능합니다.
우선 DBI connect를 하고
두번째 B필드에 대해 order by한(여기서는 2번째 field(B)를 기준으로 했습니다만.
쿼리의 order by에 여러개 field를 두어서 첫번째 기준이 동일할때는 그다음 field를
기준으로 정렬등... 쿼리만 바꾸면 조건을 편하게 수정가능합니다.)
query를 prepare한 다음 query를 실행시키고
그결과를 찍어내기만 하면 됩니다.
쿼리결과 찍는 예제는 array dump, field명을 지정하는 hashref(두개는 주석처리)
맨마지막에 Text::CSV_XS 모듈을 이용한 csv로 찍는 3가지가 있습니다.

sort_list.pl

use DBI;
use Text::CSV_XS;

#When DOS text format
my $dbh=DBI->connect("DBI:CSV:f_dir=.;csv_sep_char=,;csv_eol=\015\012") or die "Cannot connect: ".$DBI::errstr;
#When UNIX text format
#my $dbh=DBI->connect("DBI:CSV:f_dir=.;csv_sep_char=,;csv_eol=\012") or die "Cannot connect: ".$DBI::errstr;

my $sql="SELECT * FROM sort_list.txt order by B";
my $sth=$dbh->prepare($sql) or die "Cannot prepare: ".$dbh->errstr();
$sth->execute() or die "Cannot execute: ".$sth->errstr();

# ARRAY DUMP
#my @row;
#while( @row=$sth->fetchrow_array() )
#{
#    print join(" ", @row). "\n";
#}

# HASHREF DUMP
#my $row_hashref;
#while($row_hashref=$sth->fetchrow_hashref)
#{
#    print "$row_hashref->{A} $row_hashref->{B} $row_hashref->{C} $row_hashref->{D} $row_hashref->{E} $row_hashref->{F}\n";
#}

# CSV DUMP
$csv = Text::CSV_XS->new;
my @row;
my $status;
open(FILE,">sort_list_sorted.txt");

# dump each column names
$status = $csv->combine(@{ $sth->{NAME} });
print FILE $csv->string."\n";

# dump sorted data
while( @row=$sth->fetchrow_array() )
{
    $status = $csv->combine(@row);
    print FILE $csv->string."\n";
}

$sth->finish();

결과

sort_list_sorted.txt

A,B,C,D,E,F
11236,"Damon Delamar","Rita Zdaneviciute","Closed & Ready",6-12-2006,
9333,"Damon Delamar","Frank Troutman","Closed & Ready",6-7-2006,
18826,"Damon Delamar","Vivian Chien","Closed & Ready",6-27-2006,
20442,"Damon Delamar","Rita Zdaneviciute","Closed & Ready",6-27-2006,
13398,"Natalee Hengst-White","Lisa DeFazio","Closed & Ready",6-8-2006,
3497,"Natalee Hengst-White","William Gonzalez","Closed & Ready",6-13-2006,
31957,"Natalee Hengst-White","Lisa DeFazio","Closed & Ready",6-9-2006,
32547,"Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready",6-8-2006,
33567,"Natalee Hengst-White","Rita Zdaneviciute","Closed & Ready",6-22-2006,
33568,"Natalee Hengst-White","Frank Troutman","Closed & Ready",6-15-2006,
17118,"Rhonda Henry","Lisa DeFazio","Closed & Ready",6-6-2006,
24101,"Rhonda Henry","Steve Welling","Closed & Ready",6-8-2006,
6931,"Rhonda Henry","Jessica Shrode","Closed & Ready",6-15-2006,

위 결과 파일에서는 csv 규약상 공백이 들어가지 않는 field의 불필요한 "는 자동적으로 제거되었네요.

DBD::CSV, Text::CSV_XS 모듈사용에 대한 설명은
google에서 해당검색어로 찾아보면 많이 나옵니다.

pung96의 이미지

This is my code.

#!/usr/bin/perl
 
open(F,"tmp.txt");
 
while(<F>){
  @index = split;
  $List->{$index[0]}->{$index[1]}->{$_}=1;
}
 
multisort_recursive($List);
sub multisort_recursive{
  foreach $key (sort keys %{$_[0]})
  { 
    if (ref($_[0]->{$key}) ne 'HASH'){
      print $key;
    }else{
      multisort_recursive($_[0]->{$key});
    }
  }
  return;
}

tmp.txt is
1 2
3 3
2 3
1 3
3 3
1 1
2 1
2 2
3 2
3 1
lovethecorners의 이미지

친절한 답변에 감사 드립니다. 특히 aero 님의 답변은 제가 잘 활용할수 있을것 같습니다, 고맙습니다. 이번에 사용하는 파일 그냥 text 파일입니다. csv 형식처럼 제가 뽑은 data 입니다. 그래서 googling 님 말씀대로 하니 잘되는것 같습니다.

==
more than one way to do it
말로만 블로거: http://gojdweb.egloos.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.