[ ↑ INDEX ] [ NEXT → ]

Lesson 1 1行スクリプト,コマンドライン・オプション,特殊変数 ($_, $., $ARGV)


■0. 準備

指定のファイルをダウンロードし展開する。展開したら,ls コマンドで内容を表示し,dll.txt というファイルと data, script, voa というディレクトリがあることを確かめる。

   % ls perl_lesson
   data         dll.txt  script       voa

以下,perl_lesson がカレントディレクトリであるという前提で話を進めるので,perl_lesson に移動しておく。

   % cd perl_lesson

■1. コマンドラインでスクリプトを指定し実行する

   perl -e 'スクリプト' [入力ファイル] [> 出力ファイル]
スクリプト: 処理の内容を指定するもの。直前の -e はこの部分がスクリプトであることを示すオプション。スクリプトを指定する場合には,引用符で囲む。

入力ファイル: 処理の対象となるファイル。複数指定できる。ワイルドカードも使用可能 (シェルが適当なファイル名に展開してくれる)。

出力ファイル: 処理の結果の出力先。出力が指定されない場合には,ディスプレイ (コンソール) に出力される。ファイルに保存するにはリダイレクト機能(>, >>)を用いファイル名を指定し保存する。

■2. コマンドの基本的な形式

   コマンド [引数];

最後にセミコロン (;) を付ける。付けなくともよい場合もあるが,とりあえずはセミコロンを付けるとしておく。

コマンドを複数並べると,前から順番に実行する。


■3. 出力する: print

   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";'

■4. コマンドライン・オプション:-e -n -p

e: 後ろに続く部分が(ファイルではなく)スクリプトであることを示す。
n: 入力ファイルから自動的にレコード単位でデータを読み込み,スクリプトを実行する。レコードのデフォルトは行。区切り文字は [改行] (\n)。(読み込まれたデータ(後述の $_)には [改行] も含まれる。)
p: n と同じだが,最後に自動的に処理中のデータを出力する。

オプションは -pe のように複数同時に指定できる。次のようにすると,UNIX の cat コマンドと同じようにファイルを連結することができる。

   % perl -ne 'print;' voa/*
   % perl -pe '' voa/*

   cf. % cat voa/*

■5. マッチング・置換の演算子:m, s, y, tr

m/文字列/

m はマッチングの演算子。「文字列」を変数で指定することもできる。「文字列」は正規表現で指定する。

   m/worth/
s/文字列/置換文字列/
「文字列」を「置換文字列」で置き換える。「文字列」は正規表現で指定する。「文字列」を囲む文字は / 以外のものも使える。「文字列」「置換文字列」には変数を使うこともできる。
   s/^\t/     /       #行頭のタブをスペース5個に置き換える
y/文字列1/文字列2/ または tr/文字列1/文字列2/
文字単位での置換。ytr は同じものの別名。文字列1の各文字を,文字列2の対応する位置にある文字に置き換える。- による範囲指定が可能。
   y/A-Z/a-z/          #大文字を小文字に置き換える
m, s のオプション (詳細)

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

■6. 条件の指定:if

   if ( 条件 ) { 処理 }    または    処理 if ( 条件 )

「条件」が成立したら「処理」を行う。

オプション -neprint と組み合わせると,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

■7. 変数

予めシステムが用意している特殊変数と,ユーザーが自由に作って使えるユーザー変数とがある。どちらの場合も,変数名は $ で始まる。

・特殊変数

$_ 現時点では,ファイルから読み込んだレコードが入っている変数と理解しておいてよい。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 と出力

■8. 代入演算子: =

変数に値を代入するには,代入演算子 = を使う。

   $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 と同じ


□ 練習問題

練習問題A:必ずやること。

  1. dll.txt の各行の先頭に行番号を付けて出力するスクリプトを書きなさい。行番号とレコードの間にはスペース,コロン,タブなどを入れて見やすくなるようにしなさい。

  2. dll.txt から 'not' と 'to' が連続して現れる行を,行番号を付けて出力するスクリプトを書きなさい。

  3. 上のスクリプトに手を加え,問題の2語の連続をマーキングして出力するようにしなさい。マーキングは '<<not to>>' などのようにする。(やり方によっては,"Not to" が "<<not to>>" となってしまうが,今回はそれでもよいものとする。)

練習問題B:余裕があったらやってみよう。

  1. dll.txt から 'not' と 'to' が連続して現れる行を以下の形式で出力するスクリプトを書きなさい。
    a) 各行の先頭には,通し番号と行番号を付ける。
    b) 問題の2語の連続にマーキングする。

  2. dll.txt の空行以外の各行の先頭に行番号を付けて出力するスクリプトを書きなさい。

  3. dll.txt の各段落(空行で区切られた行の集まり)の改行を取るスクリプトを書きなさい。
ヒント:空行とは,\n しかない行。空行以外の行とは \n 以外の文字が最低一つある行。正規表現ではどう書けばよいか。(デフォルトでは .\n にはマッチしない。)

[ ↑ INDEX ] [ NEXT → ]