ishiducaの日記 このページをアンテナに追加 RSSフィード

2009-10-25

[][][]tsvファイルの読み書き 12:12 tsvファイルの読み書き - ishiducaの日記 を含むブックマーク はてなブックマーク - tsvファイルの読み書き - ishiducaの日記 tsvファイルの読み書き - ishiducaの日記 のブックマークコメント

タブ(\t)区切りのファイルを読み込んで、ごにょごにょ。そんでもって書き出す。 という処理をおこなうのに2次元配列に変換しておくと都合がいいので、

  • 読み込んで、2次元配列に変換するサブルーチン
  • 2次元配列をタブ区切りのデータに直して書き込むサブルーチン

sample.tsv(便宜上スペース区切り)

初めてのPerl     3600  O'REILY
続・初めてのPerl 3200  O'REILY
BLOG HACKS       2900  O'REILY
ミニマルPerl     4200  O'REILY

file.pl

sub load{
    my $file = shift;
    -e $file or die qq(not found "$file");
    my @data;
    open my $fh, "<", $file or die qq(can not open "$file");
    eval{ flock($fh,2); };
    while( <$fh> ){
        chomp;
        my @cells = split /\t/;
        push @data, \@cells;
    }
    close $fh;
    @data;
}

sub save{
    my $file = shift;
    -e $file or warn qq(not found "$file");
    my @data;
    foreach my $cell ( @_ ){
        my $str = join "\t", @{$cell};
        push @data, "$str\n";
    }
    open my $fh, ">", $file or die qq(can not open "$file");
    eval{ flock($fh,2); };
    print $fh @data;
    close $fh;
    "saved";
}

1;

上記のサブルーチンを使って金額の安い順に並び替えたリストにして書き込む

sort.pl

#!/usr/bin/perl
use strict;
use warnings;
require 'file.pl';

my @data = &load( 'sample.tsv' );
@data = sort{ $a->[1] <=> $b->[1] }@data;

print &save( 'sort_sample.tsv', @data );

exit 0;

実行

$ perl sort.pl

結果

saved

実際にファイルの中身を見てみます。

$ cat sort_sample.tsv

出力

BLOG HACKS       2900    O'REILY
続・初めてのPerl 3200    O'REILY
初めてのPerl     3600    O'REILY
ミニマルPerl     4200    O'REILY

CamiCami2011/06/05 12:20In awe of that awnser! Really cool!

hunwfqphunwfqp2011/06/05 17:367k0Pk9 <a href="http://jabwchslvcyp.com/">jabwchslvcyp</a>

gsqsmtgsqsmt2011/06/06 22:49uwYLQj , [url=http://nskgeykqazeg.com/]nskgeykqazeg[/url], [link=http://miivgnmhdygt.com/]miivgnmhdygt[/link], http://luhgyhzekwvn.com/

qjokekbsqjokekbs2011/06/07 17:45dzx81q <a href="http://gteiwjmusklf.com/">gteiwjmusklf</a>

zghleumzghleum2011/06/09 19:17Lfux4H , [url=http://tcdptdmvajwt.com/]tcdptdmvajwt[/url], [link=http://refdedletyjd.com/]refdedletyjd[/link], http://uxobwcousuoa.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20091025

2009-05-23

[][][]単純なリファレンス 18:30 単純なリファレンス - ishiducaの日記 を含むブックマーク はてなブックマーク - 単純なリファレンス - ishiducaの日記 単純なリファレンス - ishiducaの日記 のブックマークコメント

リファレンスは、値の代わりに、変数名に紐付けされたメモリ上のデータの住所を記録するスカラ変数。


内部的にはこんな感じになってるらしい

  • 変数を定義すると
  • 内部メモリのどこかにデータが格納される
  • 格納されたデータの位置(メモリアドレス)は変数の生涯を通じて変わらない
  • このデータに識別子(変数名)を通じてアクセスする代わりに、位置情報を参照(指定)してアクセスするのがリファレンスを使ったアクセス。

リファレンスを取る(参照するデータの位置情報と型を獲得する)

定義された変数(スカラー、配列、ハッシュ)のリファレンス(参照)を取るには、バックスラッシュ(\)を変数名の前に付ける

my @array = ('Ben Harper', 'Nina Shimone', 'Birdy Nam Nam');
my %hash  = ('time' => '40min', 'long' => '21km', 'cal' => '60cal');

my $referencc_array = \@aray;
my $reference_hash  = \%hash;
  • リファレンスを格納した $reference_xxx には、16進数で位置情報が格納されているので、print文を使うと、こんな感じ
print $reference_array;
print $reference_hash;

実行結果

ARRAY(0x1a2c3b)
HASH(0x80174c)

意味ないね。

参照を取ったデータから値を取り出す(デリファレンス)

print '0:$array[1]              = ', $array[1];
print '1:${$reference_array}[1] = ', ${$reference_array}[1];
print '2:$$reference_array[1]   = ', $$reference_array[1];
print '3:$reference_array->[1]  = ', $reference_array->[1];
print '';

print '0:$hash{\'time\'}              = ', $hash{'time'};
print '1:${$reference_hash}{\'time\'} = ', ${$reference_hash}{'time'};
print '2:$$refrernce_hash{\'time\'}   = ', $$reference_hash{'time'};
print '3:$reference_hash->{\'time\'}  = ', $reference_hash->{'time'};
print '';

{
    local $" = "\n";
    print "@$reference_array";
}
print '';

foreach my $key ( keys %$reference_hash ){
    printf "%4s => $reference_hash->{$key}\n", $key;
}
  • 定義された配列、ハッシュの識別子(変数名)の代わりに参照を取った変数を置き換えることで、データにアクセスする
  • 1 の例では中括弧「{}」で、識別子の境界を明示している。ただし、省略できる(省略した例が2 )
  • 省略できない場合もある。例えば「$_[1]」の様な場合。スカラー変数ではなくアクセス式だからダメ
  • 矢印「->」を使ったアクセス方法も使える。2 の頭の「$」を取っ払って、リファレンスを定義した式に「->」演算子用いてデータにアクセスする(でいいのかな?)

同一のデータを扱うということ

上の例だけだと、配列、ハッシュのコピーと変わらないように見えるけど違う。コピーしたら、コピーした時点でのデータをメモリの別の位置に新たに作るけど、リファレンスの場合は、同一のデータを扱う。

my @copy  = @array;
my $reference_array = \@array;

# 参照をいじってみる
@$reference_array = reverse @$reference_array;

$" = ", ";
print "@array";
# Birdy Nam Nam, Nina Shimone, Ben Harper
print "@copy";
# Ben Harper, Nina Shimone, Birdy Nam Nam

無名の配列、ハッシュを使う

my @array = ('Ben Harper', 'Nina Shimone', 'Birdy Nam Nam');
my %hash  = ('time' => '40min', 'long' => '21km', 'cal' => '60cal');

my $referencc_array = \@aray;
my $reference_hash  = \%hash;

配列やハッシュの定義に識別子(変数名)を定義しないで、直接リファレンスを取る形で定義する事ができる。(「無名配列コンストラクタ」「無名ハッシュコンストラクタ」)

my $reference_array = ['Ben Harper', 'Nina Shimone', 'Birdy Nam Nam'];
my $reference_hash  = {'time' => '40min', 'long' => '21km', 'cal' => '60cal'};

print $reference_array->[-1];
print $reference_hash->{'cal'};
  • 無名配列コンストラクタで配列を定義するには、「[]」を使う
  • 無名ハッシュコンストラクタでハッシュを定義するには、「{}」を使う

今のところのまとめ

データに紐を付ける方法として、名札(識別子(変数名))を使うか、住所(内部メモリの位置情報)を使うかの違い

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20090523

2009-03-13

[][][][][][][]続・続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する 00:17 続・続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する - ishiducaの日記 を含むブックマーク はてなブックマーク - 続・続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する - ishiducaの日記 続・続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する - ishiducaの日記 のブックマークコメント

前述の

とか

を見直していて、こんな書き方もできるなと

$ perl -wl -e '$,="\n"; \
> print map { join "\t",scalar localtime((stat $_)[9]), $_ } @ARGV;' *

stat関数を使って、最終更新日をオプション表示した「ls」コマンドもどきのワンライナー。スクリプト版より情報量が少ないけれど、Stat::lsMode モジュールを使わない分、手軽に使えるんじゃないかと思います。Stat::lsMode モジュールはcpanからインストールする手間があるから面倒な人もいるだろうし。

# 結果
Sun Jan 18 10:28:23 2009    sign.txt
Sun Jan 18 13:51:45 2009    内部監査手順.txt
Sun Jan 25 13:36:08 2009    temp.html
Sun Mar  1 15:20:15 2009    15477800_500.jpg
Sun Mar  8 13:11:02 2009    perl_ls
Thu Feb 19 16:06:56 2009    安全管理規程.txt

まだmap関数とstat関数が飲み込めていないけど、参考にしたところなど

SarifulSariful2012/02/23 16:10Grazi for mkiang it nice and EZ.

crvhjwrmburcrvhjwrmbur2012/02/25 03:2618jHbJ <a href="http://bhiwvkzbhltn.com/">bhiwvkzbhltn</a>

znjenwlznjenwl2012/03/01 01:306WkeFg <a href="http://tgsptrunopdl.com/">tgsptrunopdl</a>

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20090313

2009-03-08

[]続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する 22:08 続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する - ishiducaの日記 を含むブックマーク はてなブックマーク - 続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する - ishiducaの日記 続・Windowsのコマンドプロントには「ls」コマンドがないので、ワンライナーでそれっぽく代用する - ishiducaの日記 のブックマークコメント

以前にエントリーしたもの一つ前にエントリーしたものでは、同じ結果を表示しているけど、プロセス(というのかな?)がちがうので、その辺を自分用にメモ。

以前のはこう。

1: > perl -w -e 'while(<*>){ print "$_\n"; }'

これは短縮できる

  • "\n" は、起動オプションの "l" で補える
  • "$_" は、省略できる

そんな訳で、短縮版はこれ。

2: > perl -wl -e 'while(<*>){ print; }'

上記の二つは、ファイル名のリストを生成(<*>の部分)-> リストがなくなるまで一つずつ処理(出力)。 というプロセス。これと比べて、下記のものはファイルのリスト(配列)を出力しているだけ。だたし、リスト(配列)の要素と要素の間を区切る文字列にニューライン "\n" を指定しているので、同じように表示されている。

3: > perl -wl -e '$,="\n"; print <*>;'

次のは、ファイル名のリストが配列ということを明示させる例(無意味だけど)

4: > perl -wl -e '$,="\n"; print @ARGV;' *

3 と 4 は特殊変数の "$," を知らないと思いつかないので、"$," と、兄弟的な "$"" についてメモ。

  • "$," はクォートされていないハッシュまたは配列の % または @ 付きの名前(例 print @ARGV)が print の引数リストに指定された時に、要素間に挟まれる文字列
  • print の引数リストの中に現れる(クォートされていない)コンマ(例 'dog','cat')に置き換わる文字列
  • デフォルトで空
  • "$"" は配列の @ 付きの名前がダブルクォートで囲まれた(例 "@ARGV")時に各要素の間に挿入される文字列
  • デフォルトでスペース

何気に "@ARGV" のメモがなかったようなので、ここに

  • プログラムのコマンドライン引数を保持する特殊な配列
  • 入力を自動的に読み込むプログラムラインではファイル名として解釈される

KipliKipli2012/06/07 10:17Fiindng this post has solved my problem

bqtgebmvrkbqtgebmvrk2012/06/07 20:44tSnpI6 <a href="http://szepiuqnbvdq.com/">szepiuqnbvdq</a>

bgebwyvpcsbgebwyvpcs2012/06/12 03:41QuzFIv <a href="http://bevrhjshdskz.com/">bevrhjshdskz</a>

vqnxgsvqnxgs2012/06/13 09:00uKYnq0 , [url=http://jzoegncuwcdb.com/]jzoegncuwcdb[/url], [link=http://jtzcwsjlubwn.com/]jtzcwsjlubwn[/link], http://irrladcrhhgr.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20090308

2009-03-06

[][]文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた 14:14 文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた - ishiducaの日記 を含むブックマーク はてなブックマーク - 文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた - ishiducaの日記 文字数順の並び替え。もしくは、sort関数のブロックを理解したいので、ちょっとやってみた - ishiducaの日記 のブックマークコメント

$ perl -wl -e '$,="\n";print sort { length $a <=> length $b } split / /, "a pretty dog in the zoo.";'

a
in
dog
the
zoo.
pretty

ブロック内の評価は -1, 0, 1 のいずれかでいいので、こんなのも(まったく意味ないけど)。

$ perl -wl -e '$,="\n"; print sort { (($a*$b) % 3) - 1 } qw/12 10 45 9 11/;'

とすると

12
11
45
10
9

DonteDonte2011/10/08 17:37Dude, right on there borther.

owomyhowomyh2011/10/08 23:241jlJUU <a href="http://ssdikerzdfny.com/">ssdikerzdfny</a>

bxuxbwrbxuxbwr2011/10/10 19:159oAIQb , [url=http://gjdtmmddkmtd.com/]gjdtmmddkmtd[/url], [link=http://xjqbheyhkkdd.com/]xjqbheyhkkdd[/link], http://hntcbromdugl.com/

yaqwzfpkmxsyaqwzfpkmxs2011/10/11 23:49LYae8m <a href="http://rbvrcmytrhaj.com/">rbvrcmytrhaj</a>

xfmacwjxfmacwj2011/10/13 02:03Kla4tm , [url=http://lvcbuverbmqj.com/]lvcbuverbmqj[/url], [link=http://vvayhhsypbtt.com/]vvayhhsypbtt[/link], http://izaaobutpyjh.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20090306