指定のファイルをダウンロードし展開する。展開したら,ls コマンドで内容を表示し,dll.txt というファイルと data, script, voa というディレクトリがあることを確かめる。
% ls perl_lesson data dll.txt script voa
以下,perl_lesson がカレントディレクトリであるという前提で話を進めるので,perl_lesson に移動しておく。
% cd perl_lesson
perl -e 'スクリプト' [入力ファイル] [> 出力ファイル]
スクリプト: | 処理の内容を指定するもの。直前の -e はこの部分がスクリプトであることを示すオプション。スクリプトを指定する場合には,引用符で囲む。 |
入力ファイル: | 処理の対象となるファイル。複数指定できる。ワイルドカードも使用可能 (シェルが適当なファイル名に展開してくれる)。 |
出力ファイル: | 処理の結果の出力先。出力が指定されない場合には,ディスプレイ (コンソール) に出力される。ファイルに保存するにはリダイレクト機能(>, >>)を用いファイル名を指定し保存する。 |
コマンド [引数];
最後にセミコロン (;) を付ける。付けなくともよい場合もあるが,とりあえずはセミコロンを付けるとしておく。
コマンドを複数並べると,前から順番に実行する。
print 式 print 変数 print "文字列"
「式/変数/文字列」を出力する。(変数については後述。) 式や変数の場合,値を出力する。文字列は引用符で囲む。複数のものを出力する場合は,コンマ (,) で区切って並べる。出力する項目全体を ( ) で囲んでもよい。
以下のスクリプトを実行して,結果を確認しなさい。(\n は [改行] を表わす。)
1. % perl -e 'print "Hello.\n";' 2. % perl -e 'print "Hello.", "\n";' 3. % perl -e 'print ("Hello.", "\n");' 4. % perl -e 'print 2 + 3; print "\n";' 5. % perl -e 'print "2 + 3"; print "\n";'
e: | 後ろに続く部分が(ファイルではなく)スクリプトであることを示す。 |
n: | 入力ファイルから自動的にレコード単位でデータを読み込み,スクリプトを実行する。レコードのデフォルトは行。区切り文字は [改行] (\n)。(読み込まれたデータ(後述の $_)には [改行] も含まれる。) |
p: | n と同じだが,最後に自動的に処理中のデータを出力する。 |
オプションは -pe のように複数同時に指定できる。次のようにすると,UNIX の cat コマンドと同じようにファイルを連結することができる。
% perl -ne 'print;' voa/* % perl -pe '' voa/* cf. % cat voa/*
m/文字列/
s/文字列/置換文字列/m はマッチングの演算子。「文字列」を変数で指定することもできる。「文字列」は正規表現で指定する。
m/worth/
「文字列」を「置換文字列」で置き換える。「文字列」は正規表現で指定する。「文字列」を囲む文字は / 以外のものも使える。「文字列」「置換文字列」には変数を使うこともできる。y/文字列1/文字列2/ または tr/文字列1/文字列2/s/^\t/ / #行頭のタブをスペース5個に置き換える
文字単位での置換。y と tr は同じものの別名。文字列1の各文字を,文字列2の対応する位置にある文字に置き換える。- による範囲指定が可能。m, s のオプション (詳細)y/A-Z/a-z/ #大文字を小文字に置き換える
i | マッチングの際,大文字小文字を区別しない。
m/interesting/i |
g | マッチする全ての文字列を対象とする。これがないと,マッチングは一度のみ,置換の場合は最初にマッチするものしか置換しない。
s/internet/Internet/ig % perl -pe 's/ +/\n/g;' dll.txt #スペースの連続を [改行] に置き換え % perl -pe 's/\r//;' dll.txt #[復帰] を削除 |
上の説明では区切り文字として / を使ったが,それ以外の文字も使える (詳細)。m 演算子の場合,区切り文字が / ならば m を省略することが可能 (むしろ省略されることの方が多い)。次の3つは同じことを表わす。
m/worth/ /worth/ #区切り文字が / の時は m を省略可 m#worth# #/ 以外の文字を区切り文字使うこともできる
以下,区切り文字が / の場合は,m は省略して書くことにする。
以下のスクリプトを実行して,結果を確認しなさい。
1. % perl -pe 's/ /_/g' dll.txt | more 2. % perl -pe 'y/a-z/A-Z/' dll.txt | more
※ more コマンドの終了は q,強制終了は cntrl + c
if ( 条件 ) { 処理 } または 処理 if ( 条件 )
「条件」が成立したら「処理」を行う。
オプション -ne,print と組み合わせると,grep と同じ作業ができる。
% perl -ne 'if(/\bworth\b/){ print; }' dll.txt
複数の条件が同時に成り立つことを指定するには and か && を,少なくとも一つが成り立つことを指定するには or か || を用いる。
if (/\bJapan/ and /\bRussia/) #/\bJapan/ かつ /\bRussia/ にマッチしたら if (/\bJapan/ or /\bRussia/) #/\bJapan/ または /\bRussia/ にマッチしたら
以下のスクリプトを実行して,結果を確認しなさい。
1. % perl -ne 'if (/\bworth\b/) { print; }' dll.txt 2. % perl -ne 'if (s/\bworth\b/**worth**/g) { print; }' dll.txt
予めシステムが用意している特殊変数と,ユーザーが自由に作って使えるユーザー変数とがある。どちらの場合も,変数名は $ で始まる。
$_ | 現時点では,ファイルから読み込んだレコードが入っている変数と理解しておいてよい。print は対象を指定しない (引数を省略する) と,$_ の内容を出力する。
print; # print $_; と同じ |
$. | 処理中のレコードの行数。入力ファイルが複数の場合,通し番号。[ファイル単位での行番号の取得方法]
% perl -ne 'print "$. $_";' dll.txt | more % perl -ne 'print "$. $_";' voa/* | more |
$ARGV | 処理中のファイル。
% perl -ne 'if(/Japan/i){ print "$ARGV\t$_";}' voa/* |
ユーザー変数名は,A から Z までの大文字・小文字,数字,_ から構成される。ただし,数字が先頭に来てはいけない。この規則に合っていれば,自由に変数を作ることができる。値が指定されていない変数は,数値としては0,文字列としては空の文字列 "" として扱われる。
ユーザー変数の例 $count $number_of_lines $NumberOfLines $field1
$ を除いた部分を { } で括ってもよい。$count と ${count} は同じ変数を表わす。変数の直後に文字が続く場合や,変数名を変数で表わしたい時などに使うとよい。(下の例にある = は未習。)
$fruit = "apple"; print "${fruit}s"; #apples と出力
変数に値を代入するには,代入演算子 = を使う。
$count = 0 #変数に数値の0を代入 $string = "carefully" #変数に文字列 carefully を代入
次のように = の左辺と右辺に同じ変数を置くと,変数に何らかの処理をした結果が新たな変数の値となる。
$number = $number + 1 #1を加えた結果を新しい値とする
変数の値を1大きくするには,次の方法でも可能。[前置と後置の違い]
$number++ ++$number
何かの数を数えたいときには,$count などの変数を用意し,何かの条件が成立するたびに,「$count = $count + 1」を実行すれば,その時点での数を数えることができる。たとえば,次のようにすれば,"Internet" を含む行の数を数えることができる。
if (/Internet/) { $count = $count + 1; } if (/Internet/) { $count++; }
その他の代入演算子 (一部) $number += 2 #$number = $number + 2 と同じ $number -= 2 #$number = $number - 2 と同じ $number *= 2 #$number = $number * 2 と同じ $number /= 2 #$number = $number / 2 と同じ |
ヒント:空行とは,\n しかない行。空行以外の行とは \n 以外の文字が最低一つある行。正規表現ではどう書けばよいか。(デフォルトでは . は \n にはマッチしない。)