新宿Perl -見習い編 このページをアンテナに追加 RSSフィード

2007年11月16日

コードリファレンスの基本 14:24 コードリファレンスの基本 - 新宿Perl -見習い編 を含むブックマーク はてなブックマーク - コードリファレンスの基本 - 新宿Perl -見習い編 コードリファレンスの基本 - 新宿Perl -見習い編 のブックマークコメント

コードリファレンス(orコードレフ)の基本的な使い方を学びました。とりあえずハッシュに格納して呼び出す感じです。

#!/usr/bin/perl

use strict;
use warnings;

my %printer = (
  with_nl     => \&print_with_nl,
  without_nl  => \&print_without_nl,
  all_capital => \&print_all_capital,
);

sub print_with_nl {
  local $_ = shift;
  print /\n$/ ? $_ : $_."\n";
}

sub print_without_nl {
  local $_ = shift;
  s/\n$//;
  print;
}

sub print_all_capital {
  local $_ = shift;
  s/(\w+)/\U$1/g;
  print;
}

my $str = "I am learning Perl!\n";

$printer{with_nl}    ->($str);
$printer{without_nl} ->($str);
$printer{all_capital}->($str);

実行結果

I am learning Perl!
I am learning Perl!I AM LEARNING PERL!

2007年11月12日

テスト演算子の纏め 17:55 テスト演算子の纏め - 新宿Perl -見習い編 を含むブックマーク はてなブックマーク - テスト演算子の纏め - 新宿Perl -見習い編 テスト演算子の纏め - 新宿Perl -見習い編 のブックマークコメント

-e : ファイルが存在する
-z : 0バイトファイル
-s : 0バイトファイルじゃない

-f : 通常ファイル
-d : ディレクトリ
-l : シンボリックリンク
-T : テキストファイル
-B : バイナリファイル

-M : 最終更新日時からの日数
-A : 最終アクセス日時からの日数
-C : iノードが変更されてからの日数

用例は以下のように。

for my $file (glob '*') {
  print "$file\n" if -T $file;
}

grepとmapの使い分け 17:54 grepとmapの使い分け - 新宿Perl -見習い編 を含むブックマーク はてなブックマーク - grepとmapの使い分け - 新宿Perl -見習い編 grepとmapの使い分け - 新宿Perl -見習い編 のブックマークコメント

#!/usr/bin/perl

use strict;
use warnings;

chomp (my @list = `ls *.txt`);

# 元の要素から抽出したものだけのリスト
my @grepped = grep { /(.*)\.txt$/ } @list;
print join ",", @grepped, "\n";

# 元の要素のコピーから加工した別のリスト
my @mapped = map { /(.*)\.txt$/ } @list;
print join ",", @mapped, "\n";

# 元の要素自体を編集してしまう場合はfor/foreachを使うべき
s/\.txt/\.log/g for @list;
print join ",", @list, "\n";

実行結果

foo.txt,hoge.txt,var.txt,
foo,hoge,var,
foo.log,hoge.log,var.log,

2007年10月12日

Perl正規表現の基本3 03:40 Perl正規表現の基本3 - 新宿Perl -見習い編 を含むブックマーク はてなブックマーク - Perl正規表現の基本3 - 新宿Perl -見習い編 Perl正規表現の基本3 - 新宿Perl -見習い編 のブックマークコメント


置換演算子 s///

置換演算子(substitution operator)を使うと、正規表現にマッチした部分を他の文字列に置換することができます。

s/正規表現(パターン)/ダブルクォート風の文字列/

置換演算子s///は、ブール値を返却します。

オプション修飾子にgをつけるとグローバル置換(該当する全てを置換)になります。この場合、置換はオーバーラップしません。つまり、一度置き換えられた結果が再度正規表現にマッチしたとしても、それ以上置換はされません。

また、前回出てきた/iや/sといったオプション修飾子も使用することができます。

$_ = "I am studying Perl.\n";
s/I am/You are/;
print;

$_ = "putty, poderosa, winscp\n";
s/p/P/g;
print;

実行結果
You are studying Perl.
Putty, Poderosa, winscP

スラッシュ以外のデリミタを使う場合の注意点

デリミタにはスラッシュ以外を使用することができますが、左右で一対になるデリミタの場合、以下のように二つの組が別のデリミタでもOKです。

s<perl>#Perl#;
s[perl]{Perl};

結合演算子 =~ を使ってデフォルト変数以外の変数を置換する

前回、m//演算子での=~について「マッチした値を左辺に代入するのではない」と書きましたが、s///演算子で=~を使う場合は異なります。

まず、m//とs///の違いを明確に理解する必要があります。

m//  : 正規表現にマッチするかどうかを判定し、ブール値を返却する
s/// : 正規表現にマッチした場合、対象文字列のマッチする箇所を右辺値に置換し、ブール値を返却する

結合演算子=~は、これらの処理の対象として左辺値をとるものです。

つまり、s///で結合演算子=~を使用した場合、対象となる左辺にある文字列(もしくは変数が指す文字列)が置換されます。

しかし、あくまで結合演算子=~は左辺を対象として右辺の処理を行っているという点に注意が必要です。

my $str = "I like Perl.";
$str =~ s/like/love/;
print $str, "\n";

実行結果
I love Perl.

アルファベットの大文字小文字置換

アルファベットの大文字・小文字への置換は逆スラッシュエスケープを使用します。s///の右辺(置換後)において、逆スラッシュ以降に続くものを強制的に変換します。

\U : 以降全てを大文字へ
\L : 以降全てを小文字へ
\E : 変換の終了ポイント

\u : 続く一文字だけを大文字へ
\l : 続く一文字だけを小文字へ

これを応用するとワードの頭だけ大文字で以降は小文字というよくあるパターンは以下のようになります。

$target =~ s/\w+/\u\L$1/g;

以上が置換の基本的な使用方法となります。

正規表現をsplit関数のセパレータとして使用する

Perl正規表現には、今まで見てきたパターンマッチ・置換処理の他に、文字列分割時のセパレータとしての利用方法があります。

splitは正規表現によるセパレータ(区切り)の間に挟まれた文字列のリストを返却します。

my @array = split /\t/, $target;

splitを使用する際の注意点としては、「先頭の空フィールドは必ず返されるが、末尾の空フィールドは破棄される」という点です。フィールドとはセパレータで区切られた部分文字列のことです。

my @array = split /:/, "::1:2:3::::";
print $_,"," for(@array);

実行結果
,,1,2,3,

splitによって分割された文字列、または文字列の配列をひとつの文字列に結合したい場合は、join関数を使用します。

join関数は第一引数に「のり」のように挟み込む文字列(≠パターン)を指定し、第二引数以降に結合したい部分文字列を指定します。

my $joined_ex1 = join ":", "hoge", "foo", "var";
print $joined_ex1, "\n";

@array = ( "hoge", "foo", "var");
my $joined_ex2 = join ":", @array;
print $joined_ex2, "\n";

実行結果
hoge:foo:var
hoge:foo:var

と、早足ではありますが、Perl正規表現の基礎の基礎をまとめてみました。

mtqjpczrnfmtqjpczrnf2014/03/20 00:20bluiuqfsm, <a href="http://www.wztsghxamq.com/">mjesaaoigi</a> , [url=http://www.bsipxccjqx.com/]jpkgygktln[/url], http://www.qnitjlmrga.com/ mjesaaoigi

2007年10月11日

Perl正規表現の基本2 01:46 Perl正規表現の基本2 - 新宿Perl -見習い編 を含むブックマーク はてなブックマーク - Perl正規表現の基本2 - 新宿Perl -見習い編 Perl正規表現の基本2 - 新宿Perl -見習い編 のブックマークコメント


パターンマッチ m/パターン/

「/パターン/」は実際には「m/パターン/」のmを省略したショートカットです。ここで使っている「/」デリミタは他のものでも代用可能です。よく使用されるのは「{}(ブレース)」です。

オプション修飾子(option modifier)

動作をデフォルトから変えるもので閉じデリミタの直後に記述します。オプション修飾子はフラグ(flag)とも呼ばれます。

「//i」はアルファベットの大文字・小文字不問、「//s」はマッチする対象に改行文字を含みます(=全ての文字を対象とする)。

/\bhoge\b/i   # ex. hoge, HOGE, Hoge,・・・
/Do.*self/s   # ex. Don't \n Repeat \n Yourself

結合演算子 =~

結合演算子(binding operator)は右辺のパターンで左辺の文字列がマッチするかを判定し、ブール値を返却します。マッチした値を左辺に代入するのではありません。実用ではif文の条件式などでよく使用されます。

my $target = "I love Perl!";
print $target =~ /\bperl\b/i, "\n";
print $target =~ /\bruby\b/i, "\n";

出力結果
[user 20071011]$ ./binding_operator.pl 
1

[user 20071011]$

パターンに変数を埋め込む

正規表現でもダブルクォート文字列と同様に変数の展開が行われます。先ほどのサンプルは以下のように書き換えることが可能です。

my $target = "I love Perl!";
my ( $perl, $ruby ) = ( "perl", "\\bruby\\b" );
print $target =~ /\b$perl\b/i, "\n";
print $target =~ /$ruby/i, "\n";

マッチ変数 $1,$2,$3

もしかするとマッチ変数を理解してからの方が後方参照は理解しやすいのかもしれません。

後方参照、マッチ変数ともに「正規表現メモリに記憶されている値」という点は同じなのですが、以下のような違いがあります。

後方参照 \n : 正規表現内でのみ使用できる現在マッチしている値

マッチ変数 $n : 正規表現外でのみ使用できる既にマッチが完了した値

端的な例を示せば以下のようになります。

my $target="dummy";
print $1,"\n" if $target =~ /(.)\1/;

実行結果
m

また複数のマッチ変数に格納されるのは以下のような例です。

my $line = "My favorite is Perl!";
if ($line =~ /(\w+) (\w+) is (\w+)!/) {
  print "\$1:$1,\$2:$2,\$3:$3\n";
}

実行結果
$1:My,$2:favorite,$3:Perl

マッチ変数は次にパターンマッチは、次のパターンマッチが成功するとリセットされ新しい値がセットされます。逆に次のパターンマッチが失敗した場合は、前回のパターンマッチの値が保持されたままなので注意が必要です。

#そのため、パターンマッチは多くの場合ifやwhileの条件式に使われます

自動マッチ変数 $`, $&, $'

自動マッチ変数Perlに組み込まれた特殊変数です。

$` : マッチするまでスキップされた部分

$& : 正規表現でマッチした部分全体

$' : マッチしなかった残りの部分

my $line = "My favorite is Perl!";
if ( $line =~ / is (\w+)/) {
  print "\$`:$`,\$&:$&,\$':$'\n";
}

実行結果
$`:My favorite,$&: is Perl,$':!

とりあえず、今回はここまでです。次回は置換から。

#前回「前半」としたけど、二回では纏まりません。。

2007年10月09日

Perl正規表現の基本 01:11 Perl正規表現の基本 - 新宿Perl -見習い編 を含むブックマーク はてなブックマーク - Perl正規表現の基本 - 新宿Perl -見習い編 Perl正規表現の基本 - 新宿Perl -見習い編 のブックマークコメント


そもそも正規表現とは・・

文字列に対してマッチさせられるテンプレートのこと。パターンとも呼びます。

メタ文字

「*」、「+」、「?」のように直前のものが現れる回数(=量)を指定するメタ文字を「量指定子(quantifier)」といいます。

「^」、「$」のようにパターンを文字列の特定の場所に固定するものを「アンカー」といいます。

「\b」のようにワードの両端にマッチするものを特に「ワードアンカー」といいます。Perl正規表現において「ワード」とは「英数字、アンダースコアで構成されるもの」を指します。

. : 改行文字以外の任意の一文字にマッチ

* : 直前のものに0回以上マッチ
+ : 直前のものに1回以上マッチ
? : 直前のものに0or1回マッチ

^ : 文字列の先頭をあらわす
$ : 文字列の末尾をあらわす

\b : ワードの先頭または末尾をあらわす(片方のみで使用可)

グループにまとめる ()

正規表現のパターンを一つのグループに纏める場合はカッコ()でくくります。また後述しますが、()には正規表現メモリに記憶するという役割もあります。

/fred+/      # ex. fred,freddddddddd・・・
/(fred)+/    # ex. fred,fredfredfred・・・
/(fred)*/    # 任意の文字列

文字クラス []

ブラケットの中の文字のいずれか一文字にマッチします。

キャレット(^)はアンカーとして使用される場合は「文字列の先頭」をあらわしますが、文字クラス[]内では「否定」を意味します。

/[0-9]/   # ex. 0,1,2,3,4,・・,8,9
/[^0-9]/  # ex. a,b,c,A,B,C,_,・・・

よく使用されるパターンにはショートカットが用意されています。

\d    # [0-9]
\w    # [a-zA-Z0-9_]
\s    # [\f\t\n\r ]

\sは単体で使われることはまれで、人間から見て空白になっている部分にマッチするために\s*もしくは\s+の形で使用されます。

\s*   # 空白がない場合も含む
\s+   # 一個以上の空白文字がある

ショートカットの否定形はそれぞれ大文字で記述します。

\D, \W, \S

汎用の量指定子

これまでの量指定子は0回以上(*)、1回以上(+)、0/1回(?)しか指定できませんでしたが、これら以外の繰り返し回数を指定したい場合は、以下のように記述します。下限は省略できません。

/a{2,4}/   # aa, aaa, aaaaがマッチ
/a{2,}/    # aa, aaa, aaaa, aaaaa,・・・(カンマ省略不可)
/a{1,3}/   # a, aa, aaaがマッチ
/a{0,3}/   # 任意の文字列
/a{2}/     # aaのみマッチ

アンカーとワードアンカー

キャレットアンカー(^)は文字列の先頭、ドル文字アンカー($)は文字列の末尾をあらわします。

パターンが文字列全体にマッチすることを保証するためにこれらを併用することもあります。よく使われる例として空行をあらわす以下の記述法があります。

/^\s*$/

ワードアンカーは\wでマッチするもの(英数字、アンダースコアのみ)先頭もしくは末尾をあらわします。

/w.rd\b/   # ex. word, sword, ward, award,・・・
/\bw.rd/   # ex. word, wordpress, ward, warded, ・・・
/\bw.rd\b/ # ex. word, ward, ・・・
/\Bword\B/ # word以外のワード

また、ワードには、'(シングルクォート)、"(ダブルクォート)、!(エクスクラメーション)などは含まれませんので「That's "Mr.Larry"!」という文字列に含まれるワードは「That」「s」「Mr」「Larry」になります。

後方参照(backreference)

現在のパターンの処理内で正規表現メモリ内に保存された値を参照します。(後述するマッチ変数と対比すると理解しやすいかもしれません)

正規表現メモリにパターンがマッチした部分を格納するためには保存したいパターンをカッコ()でくくります。つまり、カッコにはパターンの一部分をグループにするだけでなく、そのマッチした値を正規表現メモリに格納するという機能があります。

正規表現メモリに格納された値は\1(メモリ1)、\2(メモリ2)、\3(メモリ3)・・\nで呼び出します。

以下の例は、同じ文字が二つ連続で続く文字列にマッチします。

まず、(.)でマッチした任意の一文字を正規表現メモリに記憶し、次に続く一文字とそのメモリ1がマッチするパターンです。

マッチしない場合は判定された一文字がメモリ1に記憶され、その次の一文字がメモリ1の文字とマッチするか判定します。

/(.)\1/   # ex. dummy, putty, livedoor, ・・・

複数のカッコが入れ子になったパターンも可能です。

my $backreference = "2ndsecond2ndsecond";
print "true\n" if $backreference =~ /((2nd)(second))\2/;

優先順位

正規表現において、優先順位は以下になります。ここでいう優先順位とは「より強く結びつく」という意味です。数学で「+」や「-」よりも「()」が優先されるのと同じイメージです。

カッコ>量指定子>アンカー、並び(順に並べたもの)>|(選択肢を表す縦棒/or)

優先順位の例

/^start|end$/

これは「start」で始まる文字列、もしくはendで終わる文字列を意味します。

/^(start|end)$/

これは「start」だけを含む文字列、もしくは「end」だけを含む文字列を意味します。

/^(\w+)\s+(\w+)$/

これは「ワード」「空白」「ワード」の構成でそれ以外を含まない文字列を意味します。たとえば「Learning Perl」のような文字列です。

最後の例でみるとまずカッコが優先され、次にその中の量指定子が優先されて「ワード」のかたまりと間に挟まれた一個以上の空白が確定し、最後にその並びと先頭、末尾のアンカーが同列で確定するといった感じになります。