【Perl】指定したフィールド(カラム)の取り出しオプションの作り方
2015-01-20-1
[Programming]
自分用プログラミングメモです。
実験用のPerlスクリプトを作るときに、使うフィールド(カラム)を指定する機能を入れたりするが、その部分だけ取り出して雛形化。コマンドラインオプションとの組み合わせ。
適当。TSV。
colsel-test.txt
フィールドをカンマ区切りの数字リストで指定する。"1" や "1,2" や "1,3,5,6" など。
"man cut" より:
■サンプルコード(colsel-f.pl):
■実行例:
カンマ区切りの数字リスト(1つか2つ)でフィールド範囲を指定する。"1" や "2" だと1つ。"1,3" だと 1 から 3 までのフィールド(3つ)。"2,6" だと 2 から 6 までのフィールド(5つ)。
"man sort" より:
■サンプルコード(colsel-k.pl):
■実行例:
cut で必要なフィールドだけ取り出すことを前提に(パイプで受ける)プログラムを作ればいいじゃん、という意見もあり。まったくもってその通りで、それで済むようなタスクはそれで良いかと。
実験用のPerlスクリプトを作るときに、使うフィールド(カラム)を指定する機能を入れたりするが、その部分だけ取り出して雛形化。コマンドラインオプションとの組み合わせ。
テストファイル
適当。TSV。
colsel-test.txt
身長 性別 自宅 あれ これ それ 176 1 0 1 0 1 170 0 0 0 1 1 164 0 1 1 1 0
cut式フィールド指定
フィールドをカンマ区切りの数字リストで指定する。"1" や "1,2" や "1,3,5,6" など。
"man cut" より:
-f list The list specifies fields, separated in the input by the field delimiter character (see the -d option.) Output fields are sepa- rated by a single occurrence of the field delimiter character.
■サンプルコード(colsel-f.pl):
#!/usr/bin/env perl use strict; use warnings; use Getopt::Long; my $fields = ""; GetOptions( "fields=s" => \$fields, # select only these fields (origin 1) ); my @flds = map {$_ - 1} split(/,/, $fields); while (<>) { chomp; my @cols = $fields ? (split/\t/)[@flds] : split/\t/; ### do something print "@cols\n"; }
■実行例:
% ./colsel-f.pl colsel-test.txt 身長 性別 自宅 あれ これ それ 176 1 0 1 0 1 170 0 0 0 1 1 164 0 1 1 1 0 % ./colsel-f.pl -f 1 colsel-test.txt 身長 176 170 164 % ./colsel-f.pl -f 6 colsel-test.txt それ 1 1 0 % ./colsel-f.pl -f 1,3,5 colsel-test.txt 身長 自宅 これ 176 0 0 170 0 1 164 1 1
sort式フィールド指定
カンマ区切りの数字リスト(1つか2つ)でフィールド範囲を指定する。"1" や "2" だと1つ。"1,3" だと 1 から 3 までのフィールド(3つ)。"2,6" だと 2 から 6 までのフィールド(5つ)。
"man sort" より:
-k, --key=POS1[,POS2] start a key at POS1, end it at POS2 (origin 1)
■サンプルコード(colsel-k.pl):
#!/usr/bin/env perl use strict; use warnings; use Getopt::Long; my $key_at = ""; GetOptions( "key=s" => \$key_at, # start a key at POS1, end it at POS2 (origin 1) ); my ($pos1, $pos2) = map {$_ - 1} split(/,/, $key_at, 2); while (<>) { chomp; my @cols = $key_at ? (split/\t/)[$pos1..($pos2||$pos1)] : split/\t/; ### do something print "@cols\n"; }
■実行例:
% ./colsel-k.pl colsel-test.txt 身長 性別 自宅 あれ これ それ 176 1 0 1 0 1 170 0 0 0 1 1 164 0 1 1 1 0 % ./colsel-k.pl -k 1 colsel-test.txt 身長 176 170 164 % ./colsel-k.pl -k 4 colsel-test.txt あれ 1 0 1 % ./colsel-k.pl -k 1,3 colsel-test.txt 身長 性別 自宅 176 1 0 170 0 0 164 0 1 % ./colsel-k.pl -k 2,6 colsel-test.txt 性別 自宅 あれ これ それ 1 0 1 0 1 0 0 0 1 1 0 1 1 1 0
議論
cut で必要なフィールドだけ取り出すことを前提に(パイプで受ける)プログラムを作ればいいじゃん、という意見もあり。まったくもってその通りで、それで済むようなタスクはそれで良いかと。
この記事に言及しているこのブログ内の記事