ブログトップ 記事一覧 ログイン 無料ブログ開設

サンプルコードによるPerl入門 〜 伝統と信頼のPerlを学ぼう 〜

3000-01-01

サンプルコードによるPerl入門 - 目次

 サンプルコードを中心としたPerlの入門サイトです。 Perlを使ったWebサイトの作り方も解説しています。関数やモジュールなPerlの便利な機能の解説も行っています。(スマートフォン、タブレットの場合のPCサイト表示はこちらから行うことができます)

Perl基礎 - Perlの基礎を覚えよう

 Perlの基礎について解説します。Perlのインストール、基本的な構文、配列、ハッシュ、正規表現、ファイル入出力、オブジェクト指向などを学ぶことができます。


  1. コマンドプロンプト- コマンドプロンプトの使い方
  2. Perlとは - Perlの特徴について
  3. Perlインストール - Perlのインストール方法
  4. Perl基礎文法最速マスター - Perlの基礎をすばやく学習
  5. 現代的なPerlの記述方法 - Perlの現代的な書き方
  6. 実践で役立つPerl正規表現 - Perlの正規表現で頻繁に利用するテクニック
  7. 配列とハッシュを自由に扱う - ハッシュと配列の扱い
  8. サブルーチンの作成 - サブルーチンの作成方法
  9. Perlのスコープを理解する - スコープという概念を学習
  10. ファイル入出力の基礎 - ファイルの読み書き
  11. Perlオブジェクト指向入門 - オブジェクト指向の入門
  12. デバッガの手引き - デバッガの紹介
  13. Perl豆知識 - 知っておくと便利な豆知識
  14. Perl FAQ - Perlでよくある質問に答える

Mojolicious入門 - PerlでWebサイトを作ろう

 Mojolicious入門 〜 PerlでWebサイトを作ろう 〜
Perlを学ぶ楽しい方法のひとつはWebサイトを作成してみることです。Webサイトを作成できれば、インターネット上で自分でサービスを公開することもできます。

 MojoliciousはPerlでWebサイトを作る場合の代表的なフレームワークです。Mojoliciousを使えば、簡単にWebサイトを作成することができます。Ruby on Railsを知っている方は、これのPerl番だと考えていただけると想像しやすいと思います。

Perl書籍

 Perl関連の書籍の紹介です。「サンプルコードによるPerl入門基礎編」「簡単プログラミング Perl/CGI」と「もっと自在にサーバを使い倒す 業務に役立つPerl」は僕が書いています。

Perl応用

 基礎を学び終えたら、関数とモジュールについて知るのが、上達の近道です。よく使用する関数や、モジュールについて解説しています。またデータベース操作についても学ぶことができます。

  1. よく使用する関数一覧 - よく使用する関数の紹介
  2. Perlモジュール徹底解説 - モジュールについての詳しい解説
  3. Validator::Customリファレンス - HTMLフォームのバリデーション
  4. SQLiteで学ぶデータベース操作の基礎 - SQLiteとDBIを使ったデータベース操作
  5. DBIx::Customリファレンス - データベースに便利にアクセス
  6. PDLによる統計解析 - PDLモジュールを使った統計解析
  7. PerlプログラマのためのC言語入門 - PerlプログラマのためのC言語の解説です
  8. XSによるC/C++バインディング入門 - PerlからC言語あるいはC++で書かれた関数を呼び出します
  9. Perlその他の情報

Perlリファレンス

Perl逆引き辞典

 逆引き辞典です。やりたいことをさがせます。簡単なサンプルつきです。

コメントデバッグコマンドライン引数配列
ハッシュサブルーチンモジュール数値演算
ビット演算文字列文字コード正規表現
ファイルとディレクトリファイルとディレクトリ(UNIX系OS)ファイル入出力制御構造
変数情報取得日付と時刻開発環境構築
特殊変数プラグマワンライナーPerlとMySQLの連携
自動試験プロセス間通信ソケットオブジェクト指向

Perlその他

CentOS・Red Hat Linux実践テクニック

Perl以外の技術情報

2014-08-29

データベースのテーブルの列名の設計の方針について

 データベースの列名を考えるときは、いつも迷う。こちらがたてば、あちらがたたずという状況が多い。これが正しいという確信にはいたっていませんが、こんな感じで作成すると、まぁいいんじゃないか的な方針を記述してみます。

行を識別するキーと業務用の主キーのふたつを作成する

 まず本というテーブルを考えます。最初の列は行を識別するためのキーです。次の列は、本を識別するためのキーです。これが業務用の主キーです。また本はタイトルを持つことにします。

 サンプルはMySQLで書きます。

create table book (
  row_id int primary_key auto_increment,
  id varchar(8) not null unique,
  title varchar(30) not null,
);

 注目する点は以下の点です。

  • 行IDには、プリマリー制約をつけて、オートインクリメントする
  • 本のIDには、not null制約とユニーク制約をつける

 実際の行は次のようになります。アンダーバーを引いてあるのが業務上の主キーです。

row_ididtitle
100000001Perl
200000002Ruby
300000003Python

 ここでなぜ、行を識別するキーが必要なのか、疑問に持たれる方もいるでしょう。なぜなら、業務上の主キーである本のIDで、行を一意に識別できるからです。もう少し考えていきましょう。

外部キーを持つ場合

 データベースのテーブルが、外部キーを持つとしましょう。bookテーブルに著者IDを追加します。

create table book (
  row_id int primary_key auto_increment,
  id varchar(8) not null unique,
  title varchar(30) not null,
  author_id varchar(8) not null
);

 著者テーブルを作成します。

create table author (
  row_id int primary_key auto_increment,
  id varchar(8) not null unique,
  name varchar(30) not null
);

 bookテーブルとauthorテーブルは次のようなデータになっています。

book
row_ididtitleauthor_id
100000001Perl00000001
200000002Ruby00000001
300000003Python00000002
author
row_ididname
100000001木本
200000002田中

 ここまではまだ、行IDが存在しなくても何の問題もありません。行を一意に識別できているからです。次が問題です。

外部キーが複合主キーを持つテーブルを指す場合

 たとえば、会社IDと担当者IDを複合主キーとする担当者テーブルがあったとします。staffテーブルとしましょう。

create table staff (
  row_id int primary_key auto_increment,
  company_id varchar(8) not null
  id varchar(8) not null,
  name varchar(30) not nulltitle,
  unique(company_id, id)
);

 データは次のような感じです。company_idとidが業務上の主キーです。

row_idcompany_ididname
100000001suzuki鈴木
200000002yamada山田

 ここでbookテーブルが、担当を持つ必要があるとします。さてどのように列を作成したらよいでしょうか。外部キーには行を一意に識別できる値を指定しなければなりません。

 すると次のようになります。

create table book (
  row_id int primary_key auto_increment,
  id varchar(8) not null unique,
  title varchar(30) not null,
  author_id varchar(8) not null,
  staff_row_id int not null
);
bookテーブル

 データは次のようになります。

row_ididtitleauthor_idstaff_row_id
100000001Perl000000011
200000002Ruby000000012
300000003Python000000022

 外部キーに、行を識別するキーを使えば、複合主キーを持つテーブルの行を、一意に識別できます。

行を識別するキーの欠点

 行を識別するキーの欠点は、自動的にインクリメントする値なので、開発環境と本番環境など、異なる環境ではその値が変わってきます。また、行の識別はできますが、値が意味をもたないので、参照先のテーブルを見ないと、実際に何を指しているのかがわかりません。

 すべての外部キーを行を識別するキーにしてしまうと、データベースのテーブルが見にくくなるので、業務上の主キーがひとつの場合は、外部キーとして、業務上の主キーを使うようにしています。

 けれども、外部キーが複合主キーを持つテーブルを指す場合は、行を一意に識別するためには、行IDを利用するのが一番よいと思います。これをやっておかないと、joinをするときのパフォーマンスが落ちますし、SQLのjoin区の作成が非常にめんどうになります。

まとめ

 まとめると、業務上の主キーはわかりやすくて、使いやすいが、外部キーが、複合主キーを持つテーブルを指す場合は、行を一意に識別するために、行を識別するキーを使うのがよい。

2014-08-13

配列について理解する | PerlプログラマのためのC言語入門

 C言語の配列について理解しましょう。Perlの配列は、動的な配列です。つまり、配列の大きさを気にせずに、要素を追加することができます。一方C言語の配列は、固定された大きさを持ちます。

配列の宣言と初期化

 配列の宣言は次のように行います。

型名 変数名[サイズ];

 実際の配列の宣言です。

# 配列の宣言
int nums[3];
double nums[3];
char nums[3];

 3つのサイズしか持たないので、3つの値しか代入することができません。サイズを増やすこともできません。

 {}を使って初期化を同時に行うこともできます。

# 配列の初期化
int nums[3] = {1, 2, 3};
double nums[3] = {1.5, 2.4, 6.5};
char nums[3] = {'a', 'b', 'c'};

配列のループ

 配列をループしてみましょう。配列の個数は自分で管理する必要があります。Perlのlengthのように配列の長さを取り出すことはできません。

int nums[3] = {1, 2, 3};

int i;
for (i = 0; i < 3; i++) {
  printf("%d\n", nums[i]);
}

よくある質問

解説では、配列の要素数がべた書きされて「3」という数字が二回でてきていますが、回避できませんか。

 C言語では、変数を使って、配列のサイズを指定することができません。マクロを使って定数を定義することで回避できます。C言語は、いろいろやろうとすると読みづらくなっていきますけどね。

# define NUMS_COUNT 3

int nums[NUMS_COUNT] = {1, 2, 3};

int i;
for (i = 0; i < NUMS_COUNT; i++) {
  printf("%d\n", nums[i]);
}

 けれども、通常は動的な配列を作成すると思います。以下で解説しています。

Perlのような動的な配列をC言語ではどのように作成すればよいですか

 C言語では、動的な配列を扱うテクニックは、別にあります。そのためには、「メモリを動的に確保する方法」と、「ポインタの知識」が必要になります。詳しいことは、動的配列の項目で解説したいと思いますが、サンプルを記述しておきます。

# intのポインタ型の宣言
int* nums;

# int型を3個格納できるメモリを動的に確保
nums = (int*)malloc(sizeof(int) * 3);

# 要素に代入
nums->[0] = 1;
nums->[1] = 2;
nums->[2] = 3;

# 確保したメモリの解放
free nums;
上記の方法で、動的な配列のメモリを一度に確保できることはわかりますが、push,pop,shift,unshiftなどの操作はどのように行いますか。

 Perlの配列は、動的配列で、push,pop,shift,unshift、サイズの拡張などが簡単に行えますが、C言語だけの機能ではこれを行うのは、大変めんどうです。自分で、双方向連結リストというデータ構造を自作することが必要です。

 もし、便利なデータのコンテナが必要なのであれば、C++を使うのが、現実的な解決策になると思います。C++のstd::vectorというクラスを利用すれば、Perlによく似た動的な配列が作成できます。

#include <vector>

# intの動的配列
std::vector<int> nums;

# (1, 2, 3)
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;

# (5, 1, 2, 3)
nums.push_front(5);

サンプルコード

 配列を使ったサンプルです。

#include <stdio.h>

int main () {
  int nums[3] = {1, 2, 3};
  
  int i;
  for (i = 0; i < 3; i++) {
    printf("%d\n", nums[i]);
  }
}

 実行しましょう。

gcc -o test test.c && ./test

 実行すると以下の結果を得ることができます。

1
2
3


PerlプログラマのためのC言語入門

2014-08-08

制御文と繰り返し文 | PerlプログラマのためのC言語入門

 C言語の制御文と繰り返し文を覚えましょう。

条件分岐 if 〜 else if 〜 else

 if 〜 else if 〜 else文です。

int num = 1;
if (num == 1) {
  // ...
}
else if (num == 2) {
  // ...
}
else {
  // ...
}

条件分岐 swich文

 C言語にはswich文があります。複数分岐で整数を判定するときはswich文を使えます。分岐の数が多いときはswitch文のほうがパフォーマンスがよいことが多いようです。breakを書かないと、breakより下の文が実行されてしまうので注意しましょう。

int num = 3;
switch(num) {
  case 1:
    // ...
    break;
  case 2:
    // ...
    break;
  case 3:
    // ...
    break;
  default :
    // ...
}

繰り返し while

 繰り返しをするときはwhile文を使うことができます。Perlと同じです。

int num = 0;

while (num < 4) {
  // ...
  num++;
}

繰り返し for

 繰り返しをするときはfor文を使うことができます。Perlと同じです。

int i = 0;
for (i = 0; i < 5; i++) {
  // ...
}

繰り返しからの脱出

 break文を使います。Perlのlastに該当します。

break;

次のループに進む

 continue文を使います。Perlのnextに該当します。

continue;

サンプルコード

 条件分岐と繰り返しのサンプルです。

#include <stdio.h>

int main () {
  int num = 2;
  
  if (num == 1) {
    printf("num is 1\n");
  }
  else if (num == 2) {
    printf("num is 2\n");
  }
  else {
    printf("num is other\n");
  }
  
  switch(num) {
    case 1:
      printf("num is 1\n");
      break;
    case 2:
      printf("num is 2\n");
      break;
    case 3:
      printf("num is 3\n");
      break;
    default :
      printf("num is other\n");
  }

  int k = 0;
  while (k < 4) {
    printf("k is %d\n", k);
    k++;
  }

  int i = 0;
  for (i = 0; i < 5; i++) {
    printf("i is %d\n");
  }
  
  return 0;
}


PerlプログラマのためのC言語入門

2014-08-07

C言語の構造体をPerlのオブジェクトとして扱う方法 | XSによるC/C++バインディング入門

 XSでは、構造体自体をPerlのオブジェクトとして扱うこともできます。C言語の構造体をPerlのオブジェクトとして扱う方法を解説します。

h2xsでモジュールを作成

 最初にh2xsでXS用のモジュールを作成します。

h2xs -A -n SomeModule

 こうすると「SomeModule」というディレクトリが作成されます。次のようなファイルとディレクトリが作成されます。

Changes
lib/
Makefile.PL
MANIFEST
ppport.h
README
SomeModule.xs
t/

XSファイルの記述

 XSファイルを記述しましょう。構造体のポインタをPTR2INTでsize_t型に変換しています。さらに、size_t型をSV*型に変換し、SV*型をSV*型へのリファレンスに変換し、最後にblessして、オブジェクトに変換しています。

 size_t型というのは整数型ですが、アドレスの値はsize_t型で受け取るようにします。

 取り出すときは、デリファレンスを行い、SV*に含まれるIVの値を取り出し、INT2PTRで構造体へのポインタに変換しています。

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

typedef struct {
  double x;
  double y;
} Point;

MODULE = Point		PACKAGE = Point		

void
new(...)
  PPCODE:
{
  // クラス名
  char* class_name = SvPV_nolen(ST(0));
  
  // xとy
  double x = SvNV(ST(1));
  double y = SvNV(ST(2));
  
  // 構造体の作成(ポインタとして作成)
  Point* point = (Point*)malloc(sizeof(Point));
  point->x = x;
  point->y = y;
  
  // ポインタをsize_t型に変換
  size_t point_iv = PTR2IV(point);
  
  // size_t型をSV*型に変換
  SV* point_sv = sv_2mortal(newSViv(point_iv));
  
  // SV*型のリファレンスを作成
  SV* point_svrv = sv_2mortal(newRV_inc(point_sv));
  
  // オブジェクトを作成
  SV* point_obj = sv_bless(point_svrv, gv_stashpv(class_name, 1));
  
  XPUSHs(point_obj);
  XSRETURN(1);
}

void
x(...)
  PPCODE:
{
  // オブジェクトを取得
  SV* point_obj = ST(0);
  
  // デリファレンス
  SV* point_sv = SvROK(point_obj) ? SvRV(point_obj) : point_obj;
  
  // SV*型をsize_t型に変換
  size_t point_iv = SvIV(point_sv);
  
  // size_t型をポインタに変換
  Point* point = INT2PTR(Point*, point_iv);
  
  // xを取得
  double x = point->x;
  
  // xをSV*型に変換
  SV* x_sv = sv_2mortal(newSVnv(x));
  
  XPUSHs(x_sv);
  XSRETURN(1);
}

void
y(...)
  PPCODE:
{
  // オブジェクトを取得
  SV* point_obj = ST(0);
  
  // デリファレンス
  SV* point_sv = SvROK(point_obj) ? SvRV(point_obj) : point_obj;
  
  // SV*型をsize_t型に変換
  size_t point_iv = SvIV(point_sv);
  
  // size_t型をポインタに変換
  Point* point = INT2PTR(Point*, point_iv);
  
  // xを取得
  double y = point->y;
  
  // xをSV*型に変換
  SV* y_sv = sv_2mortal(newSVnv(y));
  
  XPUSHs(y_sv);
  XSRETURN(1);
}

void
DESTORY(...)
  PPCODE:
{
  // オブジェクトを取得
  SV* point_obj = ST(0);
  
  // デリファレンス
  SV* point_sv = SvROK(point_obj) ? SvRV(point_obj) : point_obj;
  
  // SV*型をsize_t型に変換
  size_t point_iv = SvIV(point_sv);
  
  // size_t型をポインタに変換
  Point* point = INT2PTR(Point*, point_iv);
  
  // Point*を解放
  free(point);
  
  XSRETURN(0);
}

MODULE = SomeModule		PACKAGE = SomeModule		

Pointモジュールの作成

 Point.pmというファイルをlib以下においてください。SomeModuleを読み込んでいるのは、SomeModuleにバインディングの記述があるためにです。

package Point;
use SomeModule;

1;

テストスクリプト

 テストスクリプトを作成します。これは、XSファイルがあるディレクトリと同じディレクトリにおいてください。

use strict;
use warnings;
use Point;

my $point = Point->new(1, 2);
print $point->x . "\n";
print $point->y . "\n";

コンパイルして実行

 コンパイルして実行してみましょう。

perl Makefile.PL
make
perl -Mblib test.pl

 次のように出力されれば成功です。

1
2


XSによるC/C++バインディング入門