TSNET スクリプト 通 信 TSC 編 集 委 員 会 ISSN 1884-2798 1
目 次 巻 頭 言 jscripter... 3 イマジン Y さ... 4 Excel±クリック 数 取 器 (カウンター) Ver1.0 でび... 16 MeCab でルビ 振 り ムムリク... 23 Python の 文 法 草 稿 第 6 回 機 械 伯 爵... 31 バッチの 技 術 - ファイルのリネームと 移 動 jscripter... 42 覚 醒 と 進 化 試 論 II jscripter... 45 編 集 後 記 jscripter... 48 表 紙 写 真 : 撮 影 : 日 時 : 場 所 : メモ: 羊 蹄 山 の 雲 海 ムムリク 1985 年 4 月 ニセコ TSNET スクリプト 通 信 第 7 号 の 十 勝 岳 に 続 く 第 二 弾 (jscripter) 2
巻 頭 言 jscripter 新 年 の 第 15 号 が 無 事 出 る Y ささんの イマジン は 夢 の 中 で 生 まれたトランプ ゲーム お 楽 しみください でびさんからは 初 投 稿 をいただいた Excel のマクロである 数 取 器 を Excel で 実 現 し ている クリックし 過 ぎて 間 違 えた 場 合 は 引 き 算 ができて 戻 れるのが 普 通 の 数 取 器 と 違 うところ ムムリクさんの MeCab でルビ 振 り 高 度 なテキスト 処 理 をしようと 思 えば テキス トの 形 態 素 解 析 をする 必 要 が 出 てくる そこで MeCab が 登 場 する TSNET スクリプト 通 信 では 初 めて 取 り 上 げられる 勉 強 になりそう 機 械 伯 爵 さんの Python の 文 法 草 稿 の 続 編 第 6 回 文 字 列 操 作 に 関 連 したメソッド の 解 説 である 新 年 は TSNET で 質 問 して 勉 強 した PC の IP アドレスを 取 得 する 方 法 についてである デスクトップ CGI においては DHCP による IP アドレスを CGI で 取 得 できると 自 動 化 に 便 利 なのである そのうち でびさんからも サブディレクトリのファイルをサブディレクトリ 名 をファ イル 名 に 付 加 リネームして 一 つ 上 のディレクトリに 移 動 するバッチについて 質 問 され た これも 記 事 としてまとめた さて 編 集 者 は 引 き 続 きよたよたとしていて みなさんの 投 稿 を 受 け 止 めるのに 精 一 杯 となってしまった 覚 醒 と 進 化 試 論 II は DesktopWeb フレームワークを 作 る 出 発 点 としてはささやかだが 小 さな 一 歩 が 大 きく 発 展 すると 信 じている 以 上 ( 投 稿 : 2012 年 2 月 5 日 ) 3
1. このゲームは イマジン written by Yさ タイトルは 平 和 を 願 う 歌 の 邦 題 を 彷 彿 させますが 内 容 は 全 く 関 係 ありません... また 仕 事 や 恋 に 自 分 らしさを 模 索 する 女 性 を 描 いた 漫 画 とも 関 係 ありません コンピュータと 対 戦 する 形 式 のゲームで 互 いに 何 枚 かのカードを 伏 せて 配 置 し 推 理 して 先 に 全 てを 当 てた 方 が 勝 ちとなるトランプゲームです 貧 相 な 画 面 のゲーム なので 分 かりにくいのですが 双 方 が' 黒 'のカードを 伏 せて 配 置 し ' 赤 'のカードで 推 理 します (;^^ゞ 2. 動 作 環 境 は 例 によって 最 近 の awk なら OK だと 思 います ちなみに 動 作 確 認 は GNU Awk 4.0.0, mawk 1.3.3 MBCS R27 で(WinXP の DOS 窓 で) 行 なってます 3. 遊 び 方 は >gawk -f imagine.awk[enter] ~~~~~~~~~~~~~~~~^^~~~~~~~~~ 等 で 起 動 するとゲームスタートです 1) 最 初 にゲームのレベル(' 場 'のサイズ)を 選 択 してください 通 常 プレイか 練 習 プレイの どちらかを 3,5 を 入 力 して 選 びます 通 常 プレイ : 5 練 習 プレイ : 3 なお -v FIELDSIZE=5 ~~~~~~~~~~~~~~~ 4
といった 感 じでオプションを 付 けて 起 動 しても レベルを 決 定 できます 2)<セットアップ> まず 最 初 にコンピュータに 当 てさせる 自 分 の' 黒 '(スペード)のカードを 配 置 します 盤 面 に' 場 'と' 手 札 'をガイド 付 きで 表 示 されます どこに 何 のカードを 配 置 するかを ' 場 'と' 手 札 '(または 逆 順 に)2 文 字 で 入 力 して[Enter]で 決 定 してください 入 力 する 文 字 : ' 場 ': a~e ( 練 習 プレイ 時 は a~c) ' 手 札 ': 1~9,0,j,q,k ( なお"10"を 画 面 の 都 合 で'0'で 表 現 しています^.^;) また ','(カンマ)や 空 白 で 区 切 って 複 数 を 一 度 に 入 力 することもできます 例 ) a1,2b[enter] 全 ての 配 置 が 終 わったら 'z'を 入 力 して セットアップ を 終 了 してください 3)< 対 戦 > セットアップ と 同 様 に 盤 面 に' 場 'と' 手 札 'がガイド 付 きで 表 示 されます 相 手 が 伏 せて 配 置 した' 黒 '(クラブ)のカードのどの 場 所 に 何 の 数 字 (1~9,0,j,q,k)があ るかを 推 理 して 自 分 の' 赤 '(ハート)の 手 札 を 文 字 で 入 力 して[Enter]で 配 置 してくだ さい ( 入 力 する 文 字 は<セットアップ>と 同 じです ) 全 ての 推 理 配 置 が 終 わったら 'z'を 入 力 して 終 了 してください 続 けて コンピュータが 人 間 側 の 配 置 を 推 理 して' 赤 '(ダイヤ)のカードを 配 置 した 後 双 方 の 当 り 外 れの 判 定 が 行 われます a. 当 り = 置 いた' 赤 'のカードと 伏 せた' 黒 'のカードの 位 置 数 字 が 一 致 b. 外 れ = 置 いた' 赤 'のカードの 数 字 が 伏 せた' 黒 'のカードの 中 に 無 い c. 位 置 違 い = 置 いたカードの 数 字 が 伏 せたカードの 中 にあるが 位 置 が 違 う ' 当 り'の 場 合 相 手 が 伏 せて 置 いた' 黒 'のカードが 取 り 除 かれます ' 外 れ'の 場 合 自 分 が 推 理 して' 場 'に 置 いた' 赤 'のカードが 無 くなります ' 位 置 違 い'の 場 合 ' 場 'に 置 いた' 赤 'のカードはそのまま 残 ります 双 方 がカードの 推 理 を 繰 り 返 します 5
どちらかの 伏 せて 置 かれた' 黒 'のカード 全 てが 全 て 取 り 除 かれると 勝 敗 を 表 示 してゲ ーム 終 了 となります 4. 開 発 環 境 など ソースは awk 版 として 新 規 に 作 成 したものです ThinkPad の WinXP 上 のテキストエデ ィタとコマンドプロンプトな 環 境 でやってます 今 回 のトランプゲームは 一 応 元 ネタ 無 しのオリジナルです(^^; 実 はなんと 夢 の 中 で 誰 かと 遊 んでいて 目 覚 めた 時 まで 覚 えていたというものなのです w (...といってもオリジナルが 存 在 するかどうかをちゃんと 調 査 した 訳 ではないので 実 際 は 違 うのかもしれませんが) 5. その 他 本 プログラムはフリーソフトです 著 作 権 は 作 者 であるYさにあります ただし 転 載 再 配 布 改 造 消 去 は 自 由 です (できましたら 素 晴 らしい 改 造 を 加 えた 後 に TSC 編 集 委 員 会 宛 に 投 稿 してくださいませ) また このソフトを 使 用 した 事 による 損 害 が 発 生 したとしても 損 害 に 対 しては 一 切 の 責 任 を 負 いかねます 6. imagine.awk 以 下 に 本 記 事 のスクリプト imagine.awk を 収 録 します ## imagine written by Yさ BEGIN srand(); # ' 場 'のサイズ 決 定 gm=fieldsize; ## 5=normal, 3=training if(gm!="5" && gm!="3") print " <LEVEL>" print " training - 3" print " normal - 5" printf("\n Which?(3 or 5) >"); 6
do gm=""; getline gm; gm=tolower(gm); while(gm!="5" && gm!="3"); FIELDSIZE=gm+0; print "\n"; ## 初 期 設 定 # カード split("s,d,c", StrSuit, ","); StrSuit[0]="H"; split("2,3,4,5,6,7,8,9,0,j,q,k", StrRank, ","); StrRank[0]="A"; # Cards[key, 52]; ## カード 本 体 for(s=0; s<4; ++s) for(r=0; r<13; ++r) p=s*13 +r; Cards["suit", p] = s; # マーク Cards["rank", p] = r; # 数 字 # ガイド split("a,b,c,d,e", NtoA, ","); for(i=1; i<=9; ++i) Guide[i]=i ""; Guide[10]="0"; Guide[11]="j"; Guide[12]="q"; Guide[13]="k"; YOU=0; COM=1; RED=0; BLACK=1; # Field[who, kind, FIELDSIZE]; ## 場 札 0="A"~12="K",-1= 空 き # who(0= 人,1=COM) # kind(red= 攻, BLACK= 守 ) # Hands[who, suit, rank] ## 手 札 0= 未 使 用,1-5= 指 定 済,9= 当 り,-1= 取 られ 済 # who(0= 人,1=COM) # suit( 攻, 守 ( 人 :0="H",1="S" / COM:2="D",3="C")) # rank(0="a"~12="k") ## ゲームメイン do setup(); do you(red); com(red); display(); judge(); while(! allopen()); result(); while(decision("continue")=="y"); exit; 7
function setup( who,n,suit,rank) HIDE=1; ## COM の BLACK=' 守 'を 伏 せて 表 示 # ' 場 'をクリア for(who=0; who<=1; ++who) for(n=1; n<=fieldsize; ++n) Field[who,RED,n]=Field[who,BLACK,n]=-1; # ' 手 札 'をクリア for(who=0; who<=1; ++who) for(suit=0; suit<4; ++suit) for(rank=0; rank<13; ++rank) Hands[who,suit,rank]=0; # COM 用 ## 候 補 リスト for(rank=0; rank<13; ++rank) TryField[rank,0]=0; you(black); com(black); print "\n"; ## setup 用 表 示 function setupdisplay( i,n) print "\n----"; dispspace(13-fieldsize); dispfieldguide(); dispspace(13-fieldsize); dispfield(you, BLACK); print " <YOU\n"; disphands(you, BLACK); dispguide(black); ## ゲーム 用 表 示 function display( i,n,v) print "\n===="; disphands(com, RED); print ""; dispfieldguideskip(); dispfieldskip(com); dispspace(13-fieldsize*2); dispfield(com, RED); print " <COM"; dispfield(you, RED); dispspace(13-fieldsize*2); dispfieldskip(you); print " <YOU\n"; 8
disphands(you, RED); dispguide(red); # 手 札 カード 表 示 function disphands(who,kind, i) for(i=0; i<13; ++i) printf("%4s", cardstring(who, kind, i)); print ""; # 手 札 ガイド 表 示 function dispguide(kind, i,v) for(i=0; i<13; ++i) v=gethands(you, kind, i); printf("%4s", (v<0 v==9)?(""):sprintf(" %s) ", Guide[i+1])); print ""; # 場 札 カード 表 示 function dispfield(who,kind, n) for(n=1; n<=fieldsize; ++n) printf("%4s", cardstringby(n, who, kind)); function dispfieldskip(who, n) for(n=1; n<=fieldsize; ++n) printf("%4s", (Field[who,BLACK,n]==-1)?(""):cardStringBy(n, who, BLACK)); # 場 札 ガイド 表 示 function dispfieldguide( n) for(n=1; n<=fieldsize; ++n) printf(" %s) ", NtoA[n]); print ""; function dispfieldguideskip( n) for(n=1; n<=fieldsize; ++n) printf("%4s", (Field[COM,BLACK,n]==-1)?(""):sprintf(" %s) ", NtoA[n])); print ""; 9
# カードの 表 示 function cardstring(who,kind,rank, pos,v) if(rank<0) return "[ ]"; if((v=gethands(who,kind,rank))==-1) return ""; if(hide==1 && who==com && kind==black) return "[##]"; pos=cnvsuit(who,kind)*13 +rank; return sprintf((v==9)?"*%s%s*":"[%s%s]", StrSuit[Cards["suit", pos]], StrRank[Cards["rank", pos]]); function cardstringby(pos, who,kind) return cardstring(who,kind,field[who,kind,pos]); function cnvsuit(who,kind) return who*2+kind; function dispspace(num, i) for(i=0; i<num; ++i) printf("%4s", ""); ## 当 り 判 定 function judge() compare(you,com); compare(com,you); function compare(who,another, n,r,p, list,cnt) delete list; cnt=0; for(n=1; n<=fieldsize; ++n) r=field[another,black,n]; if(r!=-1 && r==field[who,red,n]) #RED->BLACK 当 り (BLACK 取 られる) sethands(who, RED, r, 9); remove(another, BLACK, r, n); else list[cnt++]=r; for(n=1; n<=fieldsize; ++n) r=field[who,red,n]; if(r!=-1 && gethands(who,red,r)!=9 && find(list,r)<0) #RED 取 られる remove(who, RED, r, n); 10
# 勝 敗 結 果 表 示 function result( y,c, s) print "\n\n ****** GAME OVER ******"; HIDE=0; ## COM の BLACK=' 守 'をオープン 表 示 display(); c=noopen(you,black); y=noopen(com,black); if(y==0 && c>0) s=" YOU WIN!"; if(y>0 && c==0) s=" YOU LOSE"; if(y==0 && c==0) s="...draw "; printf("\n%s (SCORE:%05d0)\n\n", s, ((FIELDSIZE-y)*100+c)); function allopen() if(noopen(you,black)==0 noopen(com,black)==0) return 1; return 0; function noopen(who,kind, n,q) q=0; for(n=1; n<=fieldsize; ++n) if(field[who,kind,n]!=-1) ++q; # 残 り 有 り return q; ## 場 に 出 す(COM) function com(kind, n,r,v,handlist,priority,cnt,i,j,p) if(kind==red) printf("\n>>>> COM"); # ' 場 'に 残 った 手 札 をローテーション delete handlist; cnt=0; for(r=0; r<13; ++r) n=gethands(com,kind,r); if(1<=n && n<=fieldsize) handlist[cnt++]=r; if(cnt>0) for(p=0; p<cnt; ++p) 11
r=handlist[p]; v=gethands(com,kind,r); # 未 作 成 なら 候 補 リストを 作 る if(tryfield[r,0]==0) for(n=1; n<=fieldsize; ++n) TryField[r,++TryField[r,0]]=n; # 置 いていた 場 所 と' 当 り'を 候 補 リストから 取 り 除 く for(i=1; i<=tryfield[r,0]; ) n=tryfield[r,i]; if(n==v (Field[COM,kind,n]!=-1 && gethandsby(n,com,kind)==9)) if(n==v) Field[COM,kind,n]=-1; for(j=i; j<tryfield[r,0]; ++j) TryField[r,j]=TryField[r,j+1]; --TryField[r,0]; else ++i; priority[p]=p; # 候 補 リストから 1 つ 取 り 出 して ' 場 'に 置 く sort(priority,cnt); for(p=0; p<cnt; ++p) r=handlist[priority[p]]; for(i=1; i<=tryfield[r,0]; ++i) n=tryfield[r,i]; if(field[com,kind,n]==-1) placement(com,kind,r,n); break; # ' 場 'に 手 札 から 出 す delete handlist; cnt=0; for(r=0; r<13; ++r) if(gethands(com,kind,r)==0) handlist[cnt++]=r; rndrange(cnt); # 作 業 用 に rndlist[] を 使 う p=0; r=-1; for(n=1; n<=fieldsize; ++n) if(r==-1) r=handlist[rndlist[p++]]; if(field[com,kind,n]==-1) placement(com,kind,r,n); r=-1; function swap(tbl,p1,p2, t) t=tbl[p1]; tbl[p1]=tbl[p2]; tbl[p2]=t; 12
function sort(tbl,cnt, i,j) for(i=0; i<cnt-1; ++i) for(j=0; j<cnt; ++j) if(tryfield[tbl[i],0]<tryfield[tbl[j],0]) swap(tbl,i,j); function rndrange(size, i) # 作 業 用 に rndlist[] を 使 う delete rndlist; for(i=0; i<size; ++i) rndlist[i]=i; for(i=0; i<size; ++i) swap(rndlist, rnd(size), i); function rnd(n) return int(n * rand()); ## 乱 数 ## 場 に 出 す(YOU) function you(kind) printf("\n>>>> YOU"); while(choice(kind)) ; function choice(kind, z,x,y,w,what,where) do (kind==red)?display():setupdisplay(); printf("\n Which?(1a-ke/z) >"); z=input(); if(length(z)>1) gsub(/,/," ",z); split(z, x); for(y in x) if(length(x[y])>=2) what=substr(x[y],1,1); if(isinguide(what)) where=substr(x[y],2,1); else what=substr(x[y],2,1); where=substr(x[y],1,1); put(kind,what,where); while(z!="z"); if(noopen(you,kind)==fieldsize) if(decision("ready")=="y") print ""; return 0; # 入 力 終 了 else 13
printf("\n...not Yet"); pushenter(); print ""; return 1; # 入 力 続 行 function isinguide(what, p) if(what2rank(what)>=0) return 1; return 0; function put(kind,what,where, rank,pos,v) if((rank=what2rank(what))<0) return; if((pos=where2pos(where))<0) return; if(field[you,kind,pos]!=-1 && gethandsby(pos,you,kind)==9) return; v=gethands(you,kind,rank); if(0<=v && v<=fieldsize) # 使 える' 手 札 'なら... if(field[you,kind,pos]!=-1) # ' 場 'が 空 いていなければ 空 けて... reset(you,kind,pos); if(v!=0) Field[YOU,kind,v]=-1; # 使 用 済 みなら 一 旦 戻 して... placement(you,kind,rank,pos); # ' 手 札 'を' 場 'に 置 く function find(list,val, p) for(p in list) if(list[p]==val) return p; return -1; function what2rank(what, p) if((p=find(guide,what))>=0) return p-1; return -1; function where2pos(where, n) if((n=find(ntoa,where))>=0) return n; return -1; function remove(who,kind,rank,pos) sethands(who, kind, rank, -1); 14
Field[who,kind,pos]=-1; function reset(who,kind,pos) sethandsby(pos, who, kind, 0); Field[who,kind,pos]=-1; function placement(who,kind,rank,pos) sethands(who, kind, rank, pos); Field[who,kind,pos]=rank; function gethands(who,kind,rank) return Hands[who,cnvSuit(who,kind),rank]; function gethandsby(pos, who,kind) return gethands(who,kind,field[who,kind,pos]); function sethands(who,kind,rank,v) Hands[who,cnvSuit(who,kind),rank]=v; function sethandsby(pos, who,kind,v) sethands(who,kind,field[who,kind,pos],v); function input( tmp) tmp=""; getline tmp; return tolower(tmp); function yorn( yn) do yn=input(); while(yn!="y" && yn!="n"); return yn; function decision(msg) printf(" %s?(y/n) >", msg); return yorn(); function pushenter( ) printf(" <PUSH ENTER>"); input(); ( 投 稿 : 2012 年 1 月 31 日 ) 15
数 取 器 って 何 だ? Excel±クリック 数 取 器 (カウンター) Ver1.0 Written By でび 数 取 機 (かずとりき) という 名 称 そのものが 一 般 的 には 知 られていませんね 日 本 野 鳥 の 会 の 人 が 持 っているアレ とか 交 通 量 調 査 で 使 っているカチカチカウンタ ー って 何 ていうの? という 質 問 もネット 上 では 散 見 されます 白 状 しますが 私 も 知 りませんでした 商 品 名 は 数 取 機 って 言 うらしいですよ 文 具 屋 さんでチャンとしたものが 1000 円 くらい 最 近 は 100 円 均 一 ショップでも それなりに 使 える ものが 売 られているそうです で フリーソフトとして 配 布 されている 数 取 機 は カウンター などの 名 称 が 付 け られていることが 多 いようです カウンターソフト この 種 のカウンターソフトを 10 種 類 くらい 試 してみました 私 個 人 の 感 性 に 過 ぎませんが それらの 中 では くま 778 氏 作 カウンタ Ver.1.01 (http://www7b.biglobe.ne.jp/~kuma778/pgm/counter/counter.html)が 最 も 良 さそうでした 観 点 は わかりやすい + 多 機 能 + 現 代 的 プログラミング 言 語 で 開 発 されてい る ということです 何 よりも 見 出 し 語 を 設 定 できて CSV ファイルで 保 存 読 み 込 みが 出 来 る 点 が 優 れていますし 流 石 に 2011 年 の 暮 れの 段 階 で 昔 のソフトで 動 作 環 境 として 要 求 されて いた VB6 のランタイムを 入 れるのは 今 更 どうかなぁ という 気 がしたわけです くま 778 氏 作 の カウンタ Ver.1.01 は.Net Framework 2.0 環 境 が 必 要 なのです が Windows Vista や Windows7 には 元 々.Net 環 境 が 入 っていますからね 数 取 機 全 般 で 困 ること 文 具 屋 さんで 売 っている 数 取 機 や カウンターソフトで ちょいと 困 ったのが 2 点 一 つ 目 間 違 って 増 やしちゃった 時 に 引 き 算 をしたい! ということ どうやら 事 務 機 器 として 販 売 されているホンモノの 数 取 機 にも 引 き 算 ボタンは 無 いようです 16
慣 れちゃえば 間 違 えないでしょ? ってことなんでしょうか 二 つ 目 項 目 数 は 10 個 程 度 では 全 然 足 りない! ということ 駅 前 でのトラフィック 調 査 をやっているパイプ 椅 子 に 座 っているお 兄 さんたちは 複 数 の 数 取 機 を 画 板 のようなものに 固 定 して 使 っていますが それでも 10 個 くらいです よね だから 普 通 は 10 個 もあれば 充 分 なのでしょう キーボードに 割 り 当 てるとしたらテンキーで 10 個 とか [F1]~[F12]までで 12 個 とか が UI 的 にもシンプルですしね でも 10 個 や 12 個 では AKB の 総 選 挙 では 項 目 数 が 足 りません テニミュの 全 キャスト(2nd シーズンを 含 む)からナンバーワンのイケメンを 投 票 で 決 めるときにも 困 ります あと 30 名 を 超 える 会 員 互 選 方 式 の 選 挙 の 場 合 も 困 ります たとえば マンション 管 理 組 合 の 委 員 とか 中 学 校 の 学 級 委 員 とかですね 会 員 数 約 2,000 名 で 非 立 候 補 制 の 会 員 互 選 方 式 選 挙 の 開 票 作 業 を 手 作 業 で 正 ちゃ んマーク でやったことがありますが 集 計 が 大 変 でした その 他 計 量 言 語 学 の 分 野 で 印 刷 媒 体 ( 新 聞 や 雑 誌 など)で 特 定 の 用 語 用 字 の 使 用 度 数 を 調 べたい 場 合 に 便 利 かもしれません というか そのような 頻 度 集 計 作 業 をする 必 要 が 出 たので 仕 方 なく 作 った 本 マクロの 良 い 点 : 見 出 し 語 設 定 ができる マウスクリックで 加 算 だけでなく 減 算 もできる 見 出 し 数 の 限 度 は 104 万 8575 個 まで 設 定 可 能 (Excell2007 以 降 ) 合 計 も (セル 中 に 自 分 で 式 を 入 れておけば) 自 動 で 出 せる データ 入 力 が 終 わった 時 点 で カウント 数 の で 数 値 フィルタ を 選 択 すると 色 々 な 絞 り 込 み 閲 覧 ができる 本 マクロの 悪 い 点 : マウスクリックが 早 すぎると 該 当 セルにカーソルが 入 ってしまう 少 し 溜 め が 必 要 なんですが コレ 結 構 苛 つきます キーボード 入 力 での 加 算 用 ボタン 減 算 用 ボタンは 用 意 していない テンキーから 入 力 とかの 機 能 は 実 装 していません 候 補 数 が 106 個 を 超 えたら 割 り 当 てできないし N キーは 何 番 目 の 候 補 に 相 当 するなんて 覚 えきれないでしょ? 17
だいたい こんな 感 じです 組 み 込 み 作 業 [ 開 発 ]タブの 表 示 (Excel2010 の 場 合 ) 1.[ファイル] 画 面 左 端 の 下 の 方 に 小 さくある[オプション]から Excel オプション ウィンドウを 開 く 2. Excel オプション ウィンドウの 画 面 左 端 で[リボンのユーザー 設 定 ]を 選 択 3. 画 面 右 側 に 出 た メインタブ で 開 発 にチェックを 入 れて OK で 閉 じる マクロの 貼 り 付 け 0. 普 通 のマクロのように 標 準 モジュールではありません 1.[ 開 発 ]タブを 開 き 一 番 左 にある[Visual Basic]ボタンを 押 す 2.なんだか Excel とは 様 子 が 異 なる 画 面 が 表 示 される これが VBA Editor です 3.VBA Editor 画 面 の 左 端 にある Sheet1(Sheet1) の 真 上 で[ 右 クリック]して[コー ドの 表 示 ] 18
4.そこに 下 記 コードを 貼 り 付 ける( 行 番 号 は 入 れないこと) 5.[ファイル] [ 終 了 して Microsoft Excel へ 戻 る]で VBA Editor を 終 了 する 19
Excel の Sheet1 に 見 出 し 等 の 書 き 込 みをする 1 行 目 は A 列 ~E 列 まで 以 下 のような 感 じ,カウント 対 象,カウント 数,+,- 2 行 目 の A 列 は 1 として 下 方 向 にオートフィルで 数 値 を 増 やす 2 行 目 の D 列 と E 列 は 下 方 向 にオートフィルで+や-をコピー ファイルの 保 存 Excel2007 以 降 では マクロ 入 りファイルは 拡 張 子 が xlsm となっている Excel マクロ 有 効 ブック 形 式 で 保 存 することになっています 初 回 の 保 存 時 に 気 をつけましょう コード 01 Private Sub Worksheet_SelectionChange(ByVal Target As Range) 02 If Target.Row = 1 Then Exit Sub 03 If Target.Column >= 6 Then Exit Sub 04 If Target.Column <= 3 Then Exit Sub 20
05 If Target.Column = 4 Then 06 Application.EnableEvents = False 07 ActiveCell.Offset(0, -1).Activate 08 ActiveCell.Value = ActiveCell.Value + 1 09 ActiveCell.Offset(0, -1).Activate 10 End If 11 If Target.Column = 5 Then 12 Application.EnableEvents = False 13 ActiveCell.Offset(0, -2).Activate 14 ActiveCell.Value = ActiveCell.Value - 1 15 ActiveCell.Offset(0, -1).Activate 16 End If 17 Application.EnableEvents = True 18 End Sub コード 解 説 01 行 目 Worksheet_SelectionChange は ワークシート 上 でイベントが 発 生 した 時 に 呼 び 出 され る 特 殊 なメソッドです それを Private Sub にして マクロの 実 行 ボタンなどから 選 択 起 動 するのではなく ワークシートを 開 いたときに 自 動 で 動 くようにしてあります 02 行 目 シート 中 の 1 行 目 は 見 出 し なので マウスによるセル 選 択 が 1 行 目 のセルだった 場 合 は なにもしない 処 理 にしてあります この 規 制 を 上 の 方 に 入 れておくことによって 以 降 の 記 述 をスキップして そのイベン トについては 無 視 して 終 了 します 以 下 でもそうですが Row( 行 )や Column( 列 )で 指 定 する 数 字 は 0 から 起 算 するの ではなく 1 から 起 算 するのが Excel VBA での 流 儀 のようです 03 行 目 シート 中 の F 列 目 を 含 めて 右 側 セルへの 操 作 の 場 合 は なにもしない 処 理 にしてありま す この 規 制 を 上 の 方 に 入 れておくことによって 以 降 の 記 述 をスキップして そのイベン トについては 無 視 して 終 了 します 04 行 目 シート 中 の C 列 目 を 含 めて 左 側 のセル(すなわち A~C 列 )への 操 作 の 場 合 は なにも しない 処 理 にしてあります この 規 制 を 上 の 方 に 入 れておくことによって ry) 21
05 行 目 ~10 行 目 選 択 したセルが D 列 (+)だった 場 合 アクティブセルを 同 じ 行 の 1 つ 左 のセル C 列 (カウント 数 )に 移 し(07 行 目 ) 既 に 入 っている 数 値 に 1 を 加 算 し(08 行 目 ) 加 算 終 了 後 に アクティブセルをもう 1 つ 左 の B 列 (カウント 対 象 )に 移 し(09 行 目 )ます 現 在 位 置 からの Offset 指 定 は Row( 行 ),Column( 列 )の 順 に 書 きます 06 行 目 は 07~09 行 目 のセル 遷 移 や 加 算 操 作 そのものが イベントとして 認 識 されて しまうのを 防 ぐために 一 時 的 にイベント 認 識 を 抑 制 する 指 定 です 09 行 目 で 加 算 終 了 後 にアクティブセルを 他 のセルに 移 動 させるのは D 列 のセルが 選 択 されたままだと もう 一 度 加 算 を 行 いたい 場 合 に 2 回 目 のイベント 発 生 を 取 得 できな いため 敢 えて 移 動 させています この 操 作 はプログラム 上 の 都 合 なので ユーザには 無 駄 な 挙 動 にも 思 えますが 選 択 セルを 定 位 置 へ 戻 す という 風 に 受 け 止 めて 頂 くより 仕 方 ありません 11 行 目 ~16 行 目 選 択 したセルが E 列 (-)だった 場 合 の 処 理 です Column 指 定 の 数 字 が-2 になっているのは 現 在 位 置 が D 列 ではなく E 列 だからですね? あとは 05 行 目 ~10 行 目 と 見 比 べれば 何 をやっているのかは 分 かると 思 います 17 行 目 06 行 目 と 12 行 目 の 指 定 を 解 除 しています 感 想 ユーザーフォームで 一 個 ずつボタンを 作 るのは 面 倒 くさかったのです ちょっと 動 作 がトロいので クリックするタイミングによって 引 っかかりを 感 じるのが 難 点 ですが セル 選 択 をイベントとして 取 得 することで 思 惑 通 りのものが 一 応 でき ました よかったよかった ライセンス 本 マクロコードについては クリエイティブ コモンズ ライセンス(CC ライセンス ) 表 示 - 非 営 利 - 継 承 2.1 日 本 (CC BY-NC-SA 2.1) を 採 用 します 詳 しくは http://creativecommons.org/licenses/by-nc-sa/2.1/jp/ 並 びに http://creativecommons.org/licenses/by-nc-sa/2.1/jp/legalcode をご 覧 下 さい ( 投 稿 : 2012 年 2 月 2 日 ) 22
MeCab でルビ 振 り ムムリク テキスト 読 み 上 げ 機 能 などで 日 本 語 を 読 ませるとき どうしても 漢 字 や 熟 語 によっては 期 待 したような 読 み 方 をしてくれないことがあります それならばきちんとしたルビを 振 っておくのが 一 番 なのかと 思 うのですが 手 作 業 ですべてのルビを 振 るのは 大 変 です( 読 み 上 げ 機 能 がルビに 対 応 しているかどうかという 問 題 もあるかもしれませんが) そこで 形 態 素 解 析 の MeCab (めかぶ)を 使 ってルビ 振 りを 行 わせてみることにしま した MeCab と Ruby を 使 って 処 理 してみます MeCab のインストール Windows 用 にはバイナリーパッケージが 用 意 されているので そちらをダウンロードし ます(http://mecab.sourceforge.net/#download) 2012 年 1 月 現 在 での 最 新 バージョ ンは 0.991 でした インストールするとデスクトップに MeCab アイコンができるの で 実 行 するとコンソールが 開 きます ここに 日 本 語 文 章 を 入 力 してリターンキーを 押 すと 解 析 結 果 が 表 示 されます きちんと 動 いていることを 確 かめておきましょう スタートメニューにある MeCab のフォルダには 辞 書 ファイルの 文 字 コードを 変 換 する メニューもあるので 必 要 に 応 じて 手 軽 に 変 換 できます MeCab-Ruby バインディング さまざまなスクリプト 言 語 などで 使 用 するためのバインディングは 別 に 用 意 されていま す(ダウンロードページから mecab-ruby-x.xxx.tar.gz をダウンロード:x.xxx はバー ジョン 番 号 ) しかし Windows ですぐに 使 える 状 態 にはなっていないため 自 分 で make する 必 要 があります また 説 明 されている 手 順 通 りに 行 ってもうまくいかなかっ たり コンパイラを 用 意 するという 必 要 もあり Windows ではやや 使 いにくい 印 象 もある かもしれません ウェブを 検 索 しているとそのための 対 策 としていろいろ 行 われているようです libmecab.dll ファイルを 直 接 扱 う 方 法 や IO::popen を 利 用 する 方 法 などが 紹 介 されて います (http://www.freia.jp/taka/blog/758/ が 詳 しいです) 情 報 を 参 考 に 試 してみたところ 一 応 make して 使 えているようなので 参 考 までにその 手 順 を 示 します (この 手 順 で 問 題 がないのかどうかは 未 確 認 です) なお 事 前 にフリーで 使 えるマイクロソフトの Visual C++ 2010 Express (http://www.microsoft.com/japan/msdn/vstudio/express/)などをインストールしてコ ンパイルできる 環 境 を 用 意 しておきます 23
1. mecab-ruby バインディングのソースファイルをダウンロードする 2. アーカイブを 展 開 して extconf.rb を 編 集 する ----- extconf.rb 編 集 前 ---- require 'mkmf' mecab_config = with_config('mecab-config', 'mecab-config') use_mecab_config = enable_config('mecab-config') `mecab-config --libs-only-l`.chomp.split.each lib have_library(lib) $CFLAGS += ' ' + `#mecab_config --cflags`.chomp have_header('mecab.h') && create_makefile('mecab') ---------------------------- ----- extconf.rb 編 集 後 ---- require 'mkmf' #mecab_config = with_config('mecab-config', 'mecab-config') #use_mecab_config = enable_config('mecab-config') #`mecab-config --libs-only-l`.chomp.split.each lib # have_library(lib) # #$CFLAGS += ' ' + `#mecab_config --cflags`.chomp $CFLAGS += ' -IC:/PROGRA~2/MeCab/sdk' $LOCAL_LIBS += ' libmecab.lib' $LIBPATH << 'C:/PROGRA~2/MeCab/sdk' have_header('mecab.h') && create_makefile('mecab') ----------------------------- MeCab を 標 準 のインストール 先 にそのまま 入 れた 場 合 C:\Program Files (x86)\mecab 以 下 にインストールされますが 半 角 スペースを 含 んだファイル 名 をパスとして 指 定 する 24
とスペースのところでそれぞれが 分 断 されてしまい 正 しく 認 識 されません そのため PROGRA~2 のように 短 縮 名 を 指 定 する 必 要 があります # でコメントアウトした 元 もとの 部 分 は 面 倒 であれば 削 除 してもかまいません 3. Makefile を 作 る Ruby にパスの 通 ったコンソールを 開 き mecab-ruby-0.991 のフォルダに 移 動 します >ruby extconf.rb として Makefile を 作 ります 4. Makefile を 編 集 して make する Makefile の 中 にある Ruby のパスなども 多 くの 場 合 C:\Program Files (x86) 以 下 に あります そこで この 部 分 も 先 ほどの extconf.rb の 場 合 と 同 様 に 修 正 をします 編 集 としてはこれだけなので Visual Studio 2010 などのコンソールを 開 き Makefile のあるフォルダに 移 動 してから nmake を 実 行 してみると ruby.h のビルド 方 法 が 指 定 さ れていません と 表 示 してエラーになります そこで Makefile の 最 下 行 にある $ (OBJS): の 行 をコメントアウトしておきます #$(OBJS):.;$(VPATH)$(hdrdir)/ruby.h.;$(VPATH)$(hdrdir)/ruby/defines.h $ (arch_hdrdir)/ruby/config.h 再 度 nmake するとしばらくして MeCab.so ファイルが 作 成 されます 現 状 では 問 題 な く 使 えているようですが なんらかの 問 題 が 内 在 しているのかどうかはわからないので そのつもりでご 使 用 ください Ruby から 使 う 実 際 に Ruby から 使 ってみます ここでは 1.9.3-p0 を 使 っています 1.8.7 系 は 近 い 将 来 メンテナンスが 終 了 するので できるだけ 1.9 系 を 使 うことをおすすめします 手 軽 に MeCab を 使 うのであれば 実 行 するプログラムと 同 じフォルダに 先 ほど 作 成 し た MeCab.so と C:\Program Files (x86)\mecab\bin にある libmecab.dll もコピーして おきます ( 本 来 的 には Ruby のインストールフォルダの /lib や /bin 以 下 に 置 くべき ですが) mecab-ruby バインディングに 添 付 されている test.rb をコピーして 試 してみます test.rb は UTF-8 で 書 かれているので スタートメニューの MeCab フォルダから Recompile UTF-8 Dictionary を 選 択 して 辞 書 の 文 字 コードを UTF-8 に 変 更 しておき ます また require 'MeCab' を require './MeCab' と 修 正 しておきます 25
>ruby test.rb 実 行 するとコンソールには 白 い 四 角 が 多 数 表 示 され 文 字 がきちんと 表 示 されません Ruby は 1.9 系 から 文 字 エンコードについてそれまでと 少 し 変 更 があり 文 字 列 はあく までも 文 字 列 であるとして 処 理 されているそうです 文 字 列 は 自 分 の 文 字 コードを 知 って います 一 方 で MeCab から 返 される 文 字 列 は 1.8 のころと 同 じような 扱 いであるバイト 列 として 返 してくるようです Ruby からは UTF-8 で 送 られた 文 字 列 が MeCab で 処 理 されて 戻 ってくるときには ASCII-8BIT で 返 ってきます このため Ruby ではそのまま ASCII-8BIT として 処 理 して しまうので 文 字 列 が 正 しく 表 示 されません そこで 強 制 的 に 文 字 エンコードを 変 更 する force_encoding() を 使 えば 正 しく 表 示 さ れるようになります test.rb の 先 頭 のほうにある puts tagger.parse(sentence) を t = tagger.parse(sentence) puts t.force_encoding("utf-8") として 実 行 してみます -------------------------- >ruby test.rb 0.991 太 郎 名 詞, 固 有 名 詞, 人 名, 名,*,*, 太 郎,タロウ,タロー は 助 詞, 係 助 詞,*,*,*,*,は,ハ,ワ この 連 体 詞,*,*,*,*,*,この,コノ,コノ 本 名 詞, 一 般,*,*,*,*, 本,ホン,ホン を 助 詞, 格 助 詞, 一 般,*,*,*,を,ヲ,ヲ 二 名 詞, 数,*,*,*,*, 二,ニ,ニ 郎 名 詞, 一 般,*,*,*,*, 郎,ロウ,ロー を 助 詞, 格 助 詞, 一 般,*,*,*,を,ヲ,ヲ 見 動 詞, 自 立,*,*, 一 段, 連 用 形, 見 る,ミ,ミ た 助 動 詞,*,*,*, 特 殊 タ, 基 本 形,た,タ,タ 女 性 名 詞, 一 般,*,*,*,*, 女 性,ジョセイ,ジョセイ に 助 詞, 格 助 詞, 一 般,*,*,*,に,ニ,ニ 渡 し 動 詞, 自 立,*,*, 五 段 サ 行, 連 用 形, 渡 す,ワタシ,ワタシ た 助 動 詞,*,*,*, 特 殊 タ, 基 本 形,た,タ,タ 記 号, 句 点,*,*,*,*,,, 26
EOS ---------------------------- 今 度 は 正 しく 表 示 されました 続 く 他 の 部 分 についても 同 様 に force_encoding("utf- 8") を 使 うことで 正 しく 表 示 されます しかし いちいち force_encoding するのも 大 変 です 本 来 はバインディングのほうで 修 正 ができるのが 望 ましいのでしょうが ひとまず 補 完 的 な 措 置 を 取 ることにします 次 のようなファイルを 用 意 します ------- mecabex.rb --------- # encoding: UTF-8 require './MeCab' module MeCab class Tagger def parseex(arg) $enc = arg.encoding if arg.instance_of?(string) result = self.parse(arg) result.force_encoding($enc) if arg.instance_of?(string) end def parsetonodeex(arg) $enc = arg.encoding if arg.instance_of?(string) result = self.parsetonode(arg) end end end ----------------------------- test.rb に require './mecabex' を 追 加 し tagger.parse() となっている 箇 所 を tagger.parseex() と 修 正 します ここでは MeCab::Tagger の parse と parsetonode だ け 補 完 メソッドを 用 意 しましたが 必 要 に 応 じて 他 の 部 分 にも 用 意 するとよいかもしれま せん MeCab を 使 ってルビを 振 る ルビを 振 るためには Tagger::parseToNode を 使 用 したほうが 便 利 です 解 析 して 分 解 されたそれぞれを 順 に 処 理 できます ただ Node で 取 得 できる 情 報 の feature は 多 数 の 情 報 のまとまりであるため 品 詞 や 読 み 方 などだけを 取 り 出 すことができません そこで さきほどの mecabex.rb に 追 加 す ることにします class Node... end までを 追 加 します ------- mecabex.rb --------- 27
module MeCab class Node def surfaceex self.surface.force_encoding($enc) end def featureex fex = self.feature.force_encoding($enc) fexa = fex.split(/,/) @pos = fexa[0] @pos1 = fexa[1] @pos2 = fexa[2] @pos3 = fexa[3] @dec1 = fexa[4] @dec2 = fexa[5] @root = fexa[6] @reading = fexa[7] @sound = fexa[8] fex end attr_reader :pos, :pos1, :pos2, :pos3, :dec1, :dec2, :root, :reading, :sound end end ---------------------------- surface は 分 割 された 文 字 そのもの feature では 品 詞 分 類 や 原 型 読 み 発 音 などを 示 します (いささかスマートさに 欠 けているのが 難 ですが) ついで 次 のようなサンプルを 用 意 します ------- rubysample.rb ------ 1:# encoding: utf-8 2: 3:require './mecabex' 4: 5:str = " 太 郎 はこの 本 を 二 郎 を 見 た 女 性 に 渡 した " 6:KANA = Regexp.new("[ぁ-ゖァ-ヺー]") 7: 8:model = MeCab::Model.new("") 9:tagger = model.createtagger() 28
10:n = tagger.parsetonodeex(str) 11:n = n.next 12:result = "" 13:while n.next do 14: ns = n.surfaceex 15: n.featureex 16: if /\A#KANA+\z/ =~ ns or " 記 号 " == n.pos 17: str2 = ns 18: else 19: str2 = "#ns #n.reading " 20: end 21: result = result + str2 22: n = n.next 23:end 24:puts result ---------------------------- 11: で 一 度 node を 進 めているのは node でははじまりと 終 りを 示 す 特 別 の node が 必 ずはいるため それをあらかじめスキップするために 進 めています 13: では 次 の node がある 限 り 繰 り 返 すようにしているため 終 りの node では 次 がないので そこで 終 了 します ( 11: をなくし 13: の n.next を n と 変 更 して 実 行 すると 違 いがよくわ かります) 14: 15: での 主 な 目 的 は 文 字 エンコードの 処 理 です 同 時 に 15: では 細 かな 情 報 への 分 割 とアクセスを 準 備 します 16: では ひらがな カタカナ だけであるか 品 詞 として 記 号 である 場 合 にはル ビ 振 りはせず( 17: ) それ 以 外 つまり 漢 字 を 含 んでいるであろう 時 はルビを 振 る( 19: )というようにしています ルビの 表 記 は 青 空 文 庫 で 使 われる 形 式 にしています 実 行 すると 次 のような 結 果 が 表 示 されます ----------------------------- 太 郎 タロウ はこの 本 ホン を 二 ニ 郎 ロウ を 見 ミ た 女 性 ジョセイ に 渡 し ワタシ た ----------------------------- 一 応 それらしくなりました ただ ジロウ であって 欲 しいはずの 二 郎 が ニロウ となっていますし ニ ロウ と 分 かれてしまっているのも 気 になります さらに 渡 し ワタシ と 送 り 仮 名 まで 一 緒 になってしまっているのも 嬉 しくない 感 じがします 29
読 み 方 については 辞 書 登 録 を 充 実 させることで ある 程 度 対 処 することができるかもし れません 送 り 仮 名 などが 一 緒 になる 問 題 は 漢 字 部 分 とかな 部 分 を 分 割 するように 処 理 を 修 正 することで 対 処 できるでしょう また ここでは 文 章 をプログラム 内 に 用 意 しましたが テキストファイルから 読 み 込 む ようにしたほうが 実 際 的 には 便 利 です 完 全 に 正 しい 読 み 方 のルビを 自 動 的 に 振 るには 限 界 がありそうではありますが いずれ にしても 最 終 的 に 人 の 手 によって 確 認 する 作 業 は 必 要 でしょうから ある 程 度 の 精 度 でル ビが 振 れることで 作 業 は 軽 減 されるのではないでしょうか よりきちんと 処 理 しようと 思 えば もう 少 しプログラムを 修 正 する 必 要 はあるでしょう が 比 較 的 簡 単 に 扱 えるということがわかりました ( 投 稿 : 2012 年 2 月 3 日 ) 30
6-2-2-2-3-2-1-2 アルファベット 用 のメソッド Python の 文 法 TSNET スクリプト 通 信 版 草 稿 第 6 回 2012.2.3 機 械 伯 爵 初 期 の Python では 関 数 でしたが とにかく 最 初 から 存 在 した 伝 統 的 なメソッドです 英 文 の 文 字 列 全 体 を 変 換 大 文 字 / 小 文 字 の 変 換 ですが ASCII 以 外 の Unicode 文 字 もちゃんと 変 換 してくれるよ うです 全 てを 小 文 字 に 書 式 :S0.lower() S1 動 作 : 文 字 列 中 のアルファベットを 全 て 小 文 字 に 全 てを 大 文 字 に 書 式 :S0.upper() S1 動 作 : 文 字 列 中 のアルファベットを 全 て 大 文 字 に >>> s0 = "abcde abcde" >>> s0.lower() 'abcde abcde' >>> s0.upper() 'ABCDE ABCDE' 最 初 を 大 文 字 あとは 小 文 字 に 強 制 変 換 次 は 英 文 書 式 の 定 番 である 頭 文 字 のみ 大 文 字 に 変 換 するメソッドです 勿 論 マル チバイト 文 字 にもばっちし 対 応 'title'と'capitalize'の 使 い 分 けは 語 頭 と 文 頭 です 語 頭 を 大 文 字 に あとは 小 文 字 に 強 制 変 換 書 式 :S0.title() S1 動 作 :それぞれの 単 語 に 対 して 全 て 頭 大 体 小 変 換 を 行 う 語 頭 を 大 文 字 に あとは 小 文 字 に 強 制 変 換 書 式 :S0.capitalize() S1 動 作 : 文 頭 のみ 大 文 字 あとは 小 文 字 に 強 制 変 換 を 行 う 実 行 コードを 見 て その 違 いを 確 かめてみて 下 さい >>> "abcdefg".title() 'Abcdefg' >>> "abcdefg".capitalize() 'Abcdefg' >>> "abc abc abc".title() # 'title'は 語 頭 'Abc Abc Abc' >>> "abc abc abc".capitalize() # 'capitalize'は 文 頭 'Abc abc abc' 31
>>> "abc abc abc".title() # マルチバイトでも 完 全 アルファベット 扱 い 'Abc abc abc' >>> "abc abc".capitalize() 'Abc abc' >>> "abc abc".capitalize() 'Abc abc' >>> "abc abc".title() 'Abc Abc' >>> "abc abc".title() 'Abc Abc' >>> "abc あいう abc".title() # アルファベット 以 外 は 区 切 り 扱 い 'Abc あいう Abc' >>> "abc abc abc".title() # アルファベットは 連 続 とみなす 'Abc abc abc' >>> "あいう abc".capitalize() # 文 頭 でないので 反 応 しない 'あいう abc' 大 文 字 を 小 文 字 に 小 文 字 を 大 文 字 に コレが 何 に 使 えるのか 正 直 わかりませんが とりあえずあります 大 文 字 を 小 文 字 に 小 文 字 を 大 文 字 に 変 換 する 書 式 :S0.swapcase() S1 動 作 : 文 字 列 中 の 大 文 字 を 小 文 字 に 小 文 字 を 大 文 字 に 変 換 する >>> "abc Abc abc AbC".swapcase() 'AbC abc AbC abc' 6-2-2-2-3-2-1-3 文 字 種 判 別 用 メソッド 文 字 種 を 判 別 するメソッド 群 ですが どうも help の 説 明 やマニュアルの 説 明 と 食 い 違 い があるように 思 えます(help やマニュアルでは 最 低 一 文 字 でも"there is at least one character in S" と 書 いてありますが 実 際 には 指 定 された 文 字 種 以 外 の 文 字 が 混 入 してい る 場 合 は 全 て'False'が 返 ります(ver.3.2.1 現 在 ) 全 てのメソッドで Unicode 文 字 も 同 様 に 扱 われます アルファベットのみ 書 式 :S0.isalpha() bool 動 作 : 文 字 列 "S0"の 文 字 が 全 てアルファベットの 場 合 は'True'が 返 る それ 以 外 は'False'が 返 る 数 字 のみ(3つのメソッドの 相 違 については 不 明 ) 書 式 1:S0.isdecimal() bool 書 式 2:S0.isdigit() bool 書 式 3:S0.isnumelic() bool 動 作 : 文 字 列 "S0"の 文 字 が 全 て 数 字 の 場 合 は'True'が 返 る それ 以 外 は'False'が 返 る アルファベットか 数 字 書 式 :S0.isalnum() bool 動 作 : 文 字 列 "S0"の 文 字 が 全 てアルファベットか 数 字 の 場 合 は'True'が 返 る それ 以 外 は'False'が 返 る 32
識 別 子 として 使 用 可 能 な 文 字 列 か 書 式 :S0.isidentifier() bool 動 作 : 文 字 列 "S0"が 識 別 子 として 使 用 可 能 ならば'True'を 返 す(ただし 予 約 語 として 利 用 されている 文 字 列 であ っても'True'を 返 すので 形 式 のみのチェックらしい) 小 文 字 かどうか 書 式 :S0.islower() bool 動 作 : 文 字 列 "S0"に 含 まれているアルファベット 文 字 が 全 て 小 文 字 なら'True'を 返 す 大 文 字 かどうか 書 式 :S0.isupper() bool 動 作 : 文 字 列 "S0"に 含 まれているアルファベット 文 字 が 全 て 大 文 字 なら'True'を 返 す 表 示 可 能 かどうか 書 式 :S0.isprintable() bool 動 作 : 文 字 列 "S0"にエスケープ 文 字 などの 表 示 不 可 能 な 文 字 が 含 まれているいなければ'True'を 返 す 語 頭 が 大 文 字 でその 他 が 小 文 字 (タイトルスタイル)かどうか 書 式 :S0.istitle() bool 動 作 : 文 字 列 "S0"に 含 まれるアルファベットのみで 構 成 される 語 の 語 頭 が 大 文 字 で それ 以 外 が 小 文 字 であるな らば'True'を 返 す 数 字 などのアルファベット 以 外 の 文 字 は このスタイルの 単 語 の 前 後 につく 場 合 に は'True' 単 語 の 中 に 挟 まれている 場 合 は'False'を 返 す 空 白 文 字 であるかどうか 書 式 :S0.isspace() bool 動 作 : 文 字 列 "S0"が 全 てスペース タブ 改 行 などの 空 白 文 字 で 構 成 されている 場 合 は'True' そうでなければ 'False'を 返 す 出 力 テストに 関 しては あまりにも 退 屈 なので 省 略 します 6-2-2-2-3-2-1-4 検 索 / 置 換 用 メソッド 検 索 置 換 等 に 関 するメソッド 群 です 正 規 表 現 に 関 しては 're'モジュールを 使 用 しま すが 簡 単 なものに 関 しては 文 字 列 のメソッドとして 実 装 されています 文 頭 文 末 のフォーマットのテスト 文 字 列 が 指 定 した 文 字 列 ( 文 字 でも 勿 論 可 )で 始 まったり 終 わっているかを 調 べるメ ソッドです( 名 前 はおそらく "START of String WITH"と"END of String WITH"と 思 われる ) 指 定 した 文 字 列 から 始 まっているか 書 式 :S0.startswith("s0"[,i1[,i2]]) bool 動 作 : 文 字 列 "S0"が 引 数 である 文 字 列 "s0"から 始 まっているならば'True'を 返 す "i1" 整 数 オプションはチェ ックを 始 める 位 置 を "i2" 整 数 オプションはチェックを 修 了 する 位 置 を 表 す 指 定 した 文 字 で 終 わっているか 書 式 :S0.endswith("s0"[,i1[,i2]]) bool 動 作 : 文 字 列 "S0"が 引 数 である 文 字 列 "s0"で 終 わっているならば'True'を 返 す "i1" 整 数 オプションはチェッ クを 始 める 位 置 を "i2" 整 数 オプションはチェックを 修 了 する 位 置 を 表 す 33
>>> "abc def ghi".startswith("abc") True >>> "abc def ghi".startswith("abc",1) False >>> "abc def ghi".startswith("def") False >>> "abc def ghi".startswith("def",4) True >>> "abc def ghi".startswith("def",4,5)# 範 囲 が 狭 い False >>> "abc def ghi".endswith("ghi") True >>> "abc def ghi".endswith("def",0,7) True >>> "abc def ghi".endswith("def",6,7) # 範 囲 が 狭 い False 正 直 'startswith'メソッドの'end'オプション(="i1")と 'endswith'メソッドの'starts'オプション (="i2")は 意 味 が 無 いようですが 多 分 フォーマットを 揃 えてあるのだと 思 われます 検 索 してヒット 位 置 を 返 す 左 から 検 索 書 式 :S0.find(k0) int 動 作 : 文 字 列 "S0"を 左 から 検 索 し "k0"が 最 初 に 見 つかった 位 置 の 先 頭 文 字 の 位 置 を 整 数 値 で 返 す 見 つからな かった 場 合 には 'int' 型 の'-1'を 返 す 右 から 検 索 書 式 :S0.rfind(k0) int 動 作 : 文 字 列 "S0"を 右 から 検 索 し "k0"が 最 初 に 見 つかった 位 置 の 先 頭 文 字 の 位 置 を 整 数 値 で 返 す 見 つからな かった 場 合 には 'int' 型 の'-1'を 返 す 右 から 検 索 (2) 書 式 :S0.rindex(k0) int 動 作 : 文 字 列 "S0"を 右 から 検 索 し "k0"が 最 初 に 見 つかった 位 置 の 先 頭 文 字 の 位 置 を 整 数 値 で 返 す 見 つからな かった 場 合 には 順 序 列 コレクション 共 有 メソッド'index'と 同 じく 'ValueError'を 返 す >>> "abc def ghi def abc".find("def") 4 >>> "abc def ghi def abc".rfind("def") 12 >>> "abc def ghi def abc".find("xxx") -1 >>> "abc def ghi def abc".rfind("xxx") -1 >>> "abc def ghi def abc".index("def") 4 >>> "abc def ghi def abc".rindex("def") 12 >>> "abc def ghi def abc".index("xxx") Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: substring not found >>> "abc def ghi def abc".rindex("xxx") Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: substring not found 34
'find','rfind'と'index','rindex'メソッドの 違 いは ターゲットの 文 字 列 が 見 つからなかった 場 合 に '- 1'を 返 す('find' 系 )か 'ValueError'を 返 す('index' 系 )かの 違 いです 処 理 を 中 断 させたくないなら'find' 系 例 外 をキャッチしたいのなら'index' 系 と 使 い 分 けられます 文 字 列 の 置 換 簡 易 置 換 メソッドです 正 規 表 現 を 使 うまでもない 大 雑 把 な 文 字 列 置 換 は コレで 行 え ます 文 字 列 の 置 換 書 式 :S0.replace(rs0, rs1) str 動 作 : 文 字 列 "S0"の 中 に 含 まれる 全 ての"rs0"を"rs1"に 置 換 した 文 字 列 を 返 すする "rs0"に 合 致 する 文 字 列 が 見 つからずとも 元 の 文 字 列 をそのまま 返 し エラーなどは 一 切 出 さない >>> "abc def ghi def abc".replace("def","xxx") 'abc xxx ghi xxx abc' >>> "abc def ghi def abc".replace("xxx","def") # 別 にエラーは 出 ないが 置 換 もされない 'abc def ghi def abc' >>> "abc def ghi def abc".replace("def","xxx") 'abc xxx ghi def abc' 6-2-2-2-3-2-1-5 連 結 / 分 割 / 分 離 用 メソッド 文 字 列 の 連 結 分 割 / 分 離 のためのメソッド 群 です 連 結 メソッド Python の 文 字 列 連 結 メソッド'join'は 他 言 語 のユーザから 気 持 ちが 悪 い と 評 判 ( 苦 笑 )のメソッドです セパレータ 文 字 列 のメソッドとして 文 字 列 のタプルやリストなどの コレクションを 引 数 に 取 る 方 法 は 確 かに 奇 妙 です 文 字 を 操 作 する 関 数 を 廃 した 結 果 な のですが その 賛 否 はともかく 使 い 方 を 紹 介 します 文 字 列 を 連 結 書 式 :SEP.join(C) str 動 作 :コレクション"C"のアイテム( 辞 書 'dict'の 場 合 はキー)に 含 まれる 文 字 列 を"SEP"で 連 結 して 返 す なお コレクションは 文 字 列 をアイテムとするリスト タプルの 他 辞 書 や 集 合 ('set')などでも 可 能 また'str' 自 身 も 文 字 列 のコレクション なので 使 用 可 能 >>> ":".join(("abc","def","ghi")) # 普 通 の 連 結 その1 'abc:def:ghi' >>> ":".join(["abc","def","ghi"]) # 普 通 の 連 結 その2 'abc:def:ghi' >>> ":".join("abc","def","ghi") # 集 合 の 連 結 ( 順 不 同 ) 'abc:ghi:def' >>> ":".join("abc":100,"def":200,"ghi":300) # 辞 書 のキーの 連 結 ( 順 不 同 ) 'abc:ghi:def' >>> ":".join(100:"abc",200:"def",300:"ghi") # キーが 文 字 列 以 外 なら 当 然 エラー Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: sequence item 0: expected str instance, int found >>> ":".join(100:"abc",200:"def",300:"ghi".values()) # 値 を 連 結 するなら 'def:ghi:abc' >>> ":".join("abcdefghi") # 文 字 列 は れ 連 結? 'a:b:c:d:e:f:g:h:i' 35
>>> "".join(("abc","def","ghi")) # セパレータは 空 文 字 列 'abcdefghi' 見 てのとおり 文 字 列 そのものに'join'を 適 用 すると 一 文 字 一 文 字 がアイテムのシーケンス として 扱 う ので 結 果 的 には 文 字 を"SEP"で 分 離 してしまう 結 果 になります なお "SEP"を 空 文 字 列 ''とすれば セパレ ータ 無 しに 普 通 に 連 結 できます 分 割 メソッド 文 字 列 を 特 定 のセパレータ 文 字 列 で 分 割 します 文 字 列 を 検 索 してヒットする 全 ての セパレータの 箇 所 で 分 割 します 文 字 列 を 分 割 する 書 式 1:S0.split(SEP) L0 書 式 2:S0.rsplit(SEP) L0 動 作 :セパレータ 文 字 列 "SEP"を 検 索 して そこで 文 字 列 を 分 割 したリスト"L0"を 返 す 'split'はセパレータを 左 から 検 索 し 'rsplit'は 右 から 検 索 する なお "SEP"を 省 略 した 場 合 は 全 ての 空 白 文 字 (スペース タブ 改 行 )をセパレータとみなす 文 字 列 を 改 行 で 分 割 する 書 式 :S0.splitlines() L0 動 作 : 複 数 行 ある 文 字 列 を 改 行 記 号 で 区 切 って 分 割 したリストを 返 す >>> "abc:def:ghi".split(":") ['abc', 'def', 'ghi'] >>> "abc:def:ghi".rsplit(":") # 一 文 字 では 違 いは 無 し ['abc', 'def', 'ghi'] >>> "abc:@:@:def:@:@:ghi".split(":@:") ['abc', '@:def', '@:ghi'] >>> "abc:@:@:def:@:@:ghi".rsplit(":@:")# 複 数 文 字 セパレータで 違 いが 出 る ['abc:@', 'def:@', 'ghi'] >>> "abc\ndef\nghi".splitlines() # 改 行 で 分 割 ['abc', 'def', 'ghi'] >>> "abc\ndef\nghi".split() # 一 見 似 ているが ['abc', 'def', 'ghi'] >>> "abc def\tghi\njkl".split() # ホワイトスペース 全 てで 分 割 ['abc', 'def', 'ghi', 'jkl'] >>> "abc def\tghi\njkl".splitlines() # 改 行 だけ ['abc def\tghi', 'jkl'] >>> "abc def\tghi\njkl".split("\n") ['abc def\tghi', 'jkl'] 'split'と'rsplit'は セパレータが 一 文 字 の 場 合 は 違 いがありませんが 複 数 文 字 がセパレータになった 場 合 には 上 記 のように 検 索 順 序 によって 結 果 が 異 なる 場 合 があります 'splitlines()'は'split("\n")'の 省 略 形 と 考 えられます 分 離 メソッド 分 離 メソッドは 分 割 メソッドに 似 ていますが 文 字 を 分 けるのは 一 回 だけです また 分 割 メソッドではセパレータ 文 字 列 は 除 かれますが 分 離 メソッドではセパレータ 文 字 列 がその 位 置 に 残 ります 文 字 列 を 分 離 する 書 式 1:S0.partition(SEP) L0 書 式 2:S0.rpartition(SEP) L0 36
動 作 : 文 字 列 "S0"をセパレータ 文 字 列 "SEP"の 位 置 で 分 離 する リスト'L0'は["SEP の 前 の 文 字 列 ","SEP","SEP の 後 の 文 字 列 "]となる 'partition'はセパレータ 文 字 列 を 左 から 検 索 し 'rpartition'は 右 から 検 索 する >>> "a:b:c:d:e".partition(":") ('a', ':', 'b:c:d:e') >>> "a:b:c:d:e".rpartition(":") ('a:b:c:d', ':', 'e') 6-2-2-2-3-2-1-6 整 形 用 メソッド 余 分 な 文 字 を 削 ったり 文 字 列 の 位 置 を 調 整 したりするメソッド 群 です 左 右 の 文 字 を 削 除 左 右 にある 特 定 の 文 字 を 消 去 書 式 :S0.strip(CL) S1 動 作 : 文 字 列 "CL"に 含 まれる 文 字 が 文 字 列 "S0"の 左 右 にあった 場 合 それを 除 去 した 文 字 列 "S1"を 返 す "CL" は 文 字 通 り 文 字 の 並 び として 捉 えられ 並 び(シーケンス)ではなく 集 まり(セット)とみなされる つま り"CL"が"#$@"とあれば "#$@"という 一 塊 の 文 字 列 ではなく"#"と"$"と"@"というセットとして 考 えられる >>> "*abcdef***".strip("*") # 個 数 関 係 なし 'abcdef' >>> "*abcdef***".strip("**") # ばらばらに 判 断 'abcdef' >>> "*abcdef***".strip("*$") # 並 び ではない 'abcdef' >>> "$*abcdef$***".strip("*$") # 集 まり とみなされる 'abcdef' >>> "$*@@abcdef$*@**".strip("*$@") 'abcdef' >>> "***abc*def***".strip("*") # 両 端 でなければ 無 視 'abc*def' 以 下 に 挙 げる'lstrip','rstrip'は 'strip'の 左 端 のみバージョン と 右 端 のみバージョン です 左 にある 特 定 の 文 字 を 消 去 書 式 :S0.lstrip(CL) S1 動 作 :"CL"に 指 定 された 文 字 が"S0"の 左 端 にあれば 除 去 右 にある 特 定 の 文 字 を 消 去 書 式 :S0.rstrip(CL) S1 動 作 :"CL"に 指 定 された 文 字 が"S0"の 右 端 にあれば 除 去 >>> "***abc*def***".strip("*") 'abc*def' >>> "***abc*def***".lstrip("*") # 左 端 のみ 除 去 'abc*def***' >>> "***abc*def***".rstrip("*") # 右 端 のみ 除 去 '***abc*def' 37
位 置 調 整 文 字 幅 を 指 定 し そのすき 間 を 空 白 か 指 定 のパッディング 文 字 で 埋 めます 中 央 位 置 に 調 整 書 式 :S0.center(i0[, c1]) S1 動 作 : 文 字 列 "S0"を 整 数 "i0"で 指 定 された 文 字 幅 の 中 央 に 位 置 させる 文 字 幅 が"S0"より 小 さい 場 合 は 無 視 さ れる 通 常 空 白 文 字 でパッディングされるが オプションの"c1"で 指 定 された 場 合 は その 文 字 が 使 用 される "c1"は 一 文 字 のみの 文 字 列 とする 奇 数 偶 数 の 関 係 でちょうど 真 ん 中 に 位 置 できない 場 合 は 以 下 のように 処 理 される 文 字 数 が 偶 数 で 文 字 幅 が 奇 数 右 寄 り( 右 のパッディング 文 字 が 一 つ 少 ない) 文 字 数 が 奇 数 で 文 字 幅 が 偶 数 左 寄 り( 左 のパッディング 文 字 が 一 つ 少 ない) おそらく 次 のような 計 算 をしているものと 思 われる 右 のパッディング 文 字 数 = 文 字 幅 2( 切 捨 て)- 文 字 数 2( 切 捨 て) 左 のパッディング 文 字 数 = 文 字 幅 -( 文 字 数 + 右 のパッディング 文 字 数 ) 左 端 位 置 に 調 整 書 式 :S0.ljust(I[, C]) S1 動 作 : 文 字 列 "S0"を 整 数 "I"で 指 定 された 文 字 幅 の 左 端 に 位 置 させる 文 字 幅 が"S0"より 小 さい 場 合 は 無 視 さ れる 通 常 空 白 文 字 でパッディングされるが オプションの"C"で 指 定 された 場 合 は その 文 字 が 使 用 される "C"は 一 文 字 のみの 文 字 列 とする 左 端 位 置 に 調 整 書 式 :S0.rjust(i0[, c1]) S1 動 作 : 文 字 列 "S0"を 整 数 "i0"で 指 定 された 文 字 幅 の 左 端 に 位 置 させる 文 字 幅 が"S0"より 小 さい 場 合 は 無 視 さ れる 通 常 空 白 文 字 でパッディングされるが オプションの"c1"で 指 定 された 場 合 は その 文 字 が 使 用 される "c1"は 一 文 字 のみの 文 字 列 とする なお "c1"に Unicode 文 字 も 指 定 できるが あくまで 文 字 数 的 に 中 央 という 処 理 となるので ASCII 文 字 と Unicode 文 字 の 幅 が 異 なる 日 本 語 の 環 境 では 変 な 結 果 になります 打 ち 出 し 画 面 参 照 >>> "abc".center(7) ' abc ' >>> "abc".center(7,"*") '**abc**' >>> "abc".center(8,"*") # 左 寄 り '**abc***' >>> "abcd".center(7,"*") # 右 より '**abcd*' >>> "abc".center(7,"*") # 文 字 幅 はあくまで 文 字 数 指 定 '**abc**' >>> "abc".center(7,"*") '**abc**' >>> "abc".ljust(7) 'abc ' >>> "abc".ljust(7,"*") 'abc****' >>> "abc".rjust(7) ' abc' >>> "abc".rjust(7,"*") '****abc' 数 字 の 前 を"0"で 埋 める 書 式 :N0.zfill(W) N1 動 作 : 数 値 文 字 列 "N0"の 前 を 整 数 値 "W"で 指 定 した 桁 数 になるまで"0"で 埋 める ただし"N0"の 桁 数 が"W"で 示 した 桁 数 以 上 なら "N0"はそのまま 返 される なお "N0"は 数 値 文 字 列 でなくても 一 向 に 構 わないが 意 味 は 無 い N0.rjust(W,"0") と 意 味 的 には 同 じ 38
>>> "123".zfill(10) '0000000123' >>> "123".zfill(2) '123' タブの 大 きさを 調 整 する 書 式 :S0.expandtabs([TS]) S1 動 作 : 文 字 列 "S0"の 中 のタブの 大 きさを"TS"に 指 定 されたセル 数 に 指 定 して ホワイトスペースに 変 換 して"S1" に 返 す "TS"を 省 略 すると8スペースタブとしてみなされる タブとしてちゃんと 機 能 していることを 示 すために 'print' 出 力 してみました >>> tab08="abc\tdef\tghi\nabcx\tdefx\tghi".expandtabs() >>> tab10="abc\tdef\tghi\nabcx\tdefx\tghi".expandtabs(10) >>> print(tab08) abc def ghi abcx defx ghi >>> print(tab10) abc def ghi abcx defx ghi >>> tab08 'abc def ghi\nabcx defx ghi' >>> tab10 'abc def ghi\nabcx defx ghi' 6-2-2-2-3-2-1-7 変 換 用 メソッド 様 々な 文 字 列 の 変 換 を 行 うメソッドです 文 字 列 をバイトコードに 変 換 書 式 :S.encode(encode="utf-8", errors="strict") bytes 動 作 : 文 字 列 "S"をバイトコードに 変 換 する デフォルトは UTF-8 だが 例 えば"sjis"とすれば SHIFT-JIS コード に 変 換 する ただし 変 換 できなければエラーとなる エラーの 動 作 のオプションは 以 下 のとおり "strict" 'UnicodeEncodeError'を 上 げる(デフォルト) "ignore" 無 視 する( b'' を 出 力 ) "replace" 不 明 文 字 "?"に 置 き 換 える "xmlcharrefreplace" XML で 用 いられるキャラクターコードに 変 換 する >>> "abc".encode() b'abc' >>> "あいうえお".encode() b'\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a' >>> "あいうえお".encode("sjis") b'\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8' >>> "abc".encode("ascii") b'abc' >>> "あいうえお".encode("ascii") Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordin al not in range(128) >>> "あいうえお".encode("ascii","ignore") b'' >>> "あいうえお".encode("ascii","replace") b'?????' >>> "あいうえお".encode("ascii","xmlcharrefreplace") 39
b'あいうえお' 'str.encode'は 'bytes.decode'に 対 応 しているので B.decode(encode) の 書 式 で 逆 変 換 をかけられま す >>> x = "あいうえお".encode('sjis') >>> print(x.decode("sjis")) あいうえお 変 換 テーブルを 作 成 して 変 換 変 換 テーブルの 作 成 書 式 :str.maketrans(x[, y[, z]]) dict 動 作 :キーが 整 数 ( 文 字 コード 番 号 ) 値 が 変 換 文 字 (あるいは 文 字 コード)の 辞 書 を 作 成 する 1 引 数 のみの 場 合 と 2 引 数 3 引 数 の 動 作 が 異 なる 1 引 数 のみの 場 合 は キーが 文 字 番 号 として 使 用 できる 整 数 か 文 字 1 文 字 値 はそれに 加 え 'None'オブジェクト( 変 換 後 省 かれる)と 複 数 文 字 列 が 指 定 できる 2 引 数 3 引 数 の 場 合 は 第 1 引 数 と 第 2 引 数 は 文 字 数 が 同 じ 文 字 列 である 必 要 がある 第 1 引 数 に 指 定 した 文 字 が 同 じ 位 置 の 第 2 引 数 に 指 定 した 文 字 に 変 換 される なお 第 3 引 数 に 指 定 した 文 字 は'None'に 置 き 換 えられる(つま り 変 換 後 省 かれる)なお 静 的 メソッド (static method)なので 'str'オブジェクトの 位 置 に 任 意 の 文 字 列 を 置 いても 使 用 できるが その 文 字 列 は 文 字 列 クラス'str'の 呼 び 出 しに 使 用 されるだけで 何 の 意 味 も 無 い( 静 的 メソッドについては 定 義 / 変 則 参 照 メソッド/ 静 的 メソッドを 参 照 ) 変 換 テーブルに 従 って 文 字 を 変 換 書 式 :S0.translate(TD) -> S1 動 作 :"S0"の 文 字 列 を 変 換 テーブル( 辞 書 =dict オブジェクト)に 従 って 変 換 した 文 字 列 "S1"として 返 す "TD" はキーが 整 数 ( 文 字 コード 番 号 ) 値 が 文 字 文 字 コード 番 号 ( 整 数 ) 及 び'None'オブジェクトの 辞 書 である フ ォーマットさえ 正 しければ 特 に str.maketranse を 使 用 しなくても 良 い 'None'オブジェクトがマップされて いる 文 字 は 削 除 される >>> for k in "abcxyz":print(k+"="+str(ord(k)))... a=97 b=98 c=99 x=120 y=121 z=122 >>> str.maketrans("a":"x") # 1 引 数 97: 'x' >>> str.maketrans("abc","xyz") # 2 引 数 97: 120, 98: 121, 99: 122 >>> str.maketrans("abc","xyz","d") # 3 引 数 97: 120, 98: 121, 99: 122, 100: None >>> TD = str.maketrans("abc","xyz","d") >>> "aaabbbcccddd".translate(td) # テーブルを 利 用 'xxxyyyzzz' >>> "aaabbbcccddd".translate('a':'x') # テーブルを 手 打 ち 'aaabbbcccddd' >>> "aaabbbcccddd".translate(97:'x') 'xxxbbbcccddd' >>> "aaabbbcccddd".translate(97:120) 'xxxbbbcccddd' 6-2-2-2-3-2-1-8 '%' 演 算 子 を 用 いた 古 い 形 式 の 文 字 列 の 整 形 40
現 在 の 新 しい Python では 文 字 列 は format メソッドで 整 形 することが 前 提 となってい ますが 以 前 から 用 いられていた"%" 演 算 子 を 用 いた 手 軽 な 文 字 列 整 形 方 法 も 一 応 今 でも サポートされています これは C 言 語 の'printf' 関 数 で 使 用 するようなスタイルの 文 字 列 の 整 形 方 法 で '%'が 頭 につく 代 替 文 字 を 後 につづく 単 体 オブジェクトや リストや 辞 書 の 値 と 入 れ 替 えるような スタイルです 本 書 では 詳 しく 触 れませんが 古 い Python の 本 やサイト あるいはC 言 語 の 本 などを 見 ていただければ 大 体 わかります Python のマニュアルに 載 っているコードサンプルの 転 記 >>> print('%(language)s has %(number)03d quote types.' %... 'language': "Python", "number": 2) Python has 002 quote types. [by "The Python Standard Library" "4.6.2. Old String Formatting Operations"] 41
1. はじめに バッチの 技 術 - ファイルのリネームと 移 動 jscripter(まとめ) TSNET でのでびさんの 表 題 の 課 題 についての 検 討 結 果 を 簡 単 にまとめる でびさん Y ささん KIMURA さん ami さんのバッチや 説 明 を 検 討 してまとめている ありがとうござ いました 2. 課 題 あるディレクトリでバッチを 実 行 して ディレクトリ 内 のサブディレクトリにあるファ イルのファイル 名 の 先 頭 に サブディレクトリ 名 を_を 挟 んで 付 加 した 名 前 にリネームし サブディレクトリからバッチを 実 行 したディレクトリに 移 動 させる 3.バッチ 1(Y ささんのバッチから) わかってみれば なんということはない cmd.exe を 実 行 して バッチコマンドの 仕 様 を 確 認 して 下 記 のバッチの 記 述 と 対 比 させてみよう 例 えば for /? を 実 行 してみ る ちなみに %%~nxf は ファイル 名 と 拡 張 子 に 展 開 されることがわかる -----^ for /d %%d in (*) do for %%f in ("%%d\*.*") do ren "%%f" "%%d_%%~nxf" for /r %%f in (*) do move "%%f". -----$ 4.バッチ2(aMI さんのバッチから) バッチ 1 では 入 れ 子 になっている for~in~do の 構 造 を call でサブルーチンを 呼 ぶよ うに 分 離 している call /? で 仕 様 を 確 認 してみること -----^ for /d %%d in ( * ) do call :loop1 "%%d" exit /b :loop1 pushd %1 for %%f in ( * ) do call :loop2 %1 "%%f" popd exit /b :loop2 42
ren %2 %1_%2 move %1_%2.. exit /b -----$ 5. 半 角 空 白 を 含 むディレクトリ 名 やファイル 名 への 対 応 上 記 のバッチはいずれも ディレクトリ 名 やファイル 名 パスが 文 字 列 として 展 開 され る 変 数 出 力 部 分 をダブルクォート "" で 括 っている 半 角 空 白 をディレクトリ 名 やファ イル 名 が 含 んでいる 場 合 には 必 須 である 代 入 される 変 数 入 力 部 分 にはこの 操 作 は 不 要 で ある 6.cmd.exe のコマンド 拡 張 機 能 setlocal /? を 調 べると 最 後 の 方 に 次 のように 記 載 されている -----^ VERIFY OTHER 2>nul SETLOCAL ENABLEEXTENSIONS IF ERRORLEVEL 1 echo 拡 張 機 能 を 有 効 にできません この 方 法 が 使 えるのは 古 いバージョンの CMD.EXE では SETLOCAL は ERRORLEVEL の 値 を 設 定 しないためです VERIFY コマンドに 誤 った 引 数 を 指 定 すると ERRORLEVEL の 値 は 0 以 外 の 値 に 初 期 化 されます -----$ あなたの 環 境 で 前 記 のバッチがうまく 動 かない 場 合 には これを 利 用 して 確 かめる 必 要 があるかもしれない コマンド 拡 張 機 能 はデフォルトで 有 効 になっている レジストリの HKEY_LOCAL_MACHINE Software Microsoft Command Processor のキーの 値 EnableExtensions が 1 であれば 有 効 であることが 確 認 できる デフォルト は 1 である 前 記 バッチでコマンド 拡 張 機 能 が 有 効 である 必 要 があるコマンドは 次 のとおりである (1) コマンド 拡 張 機 能 を 有 効 にすると call のターゲットとしてラベルが 使 えるように なる 詳 しくは call /? の 出 力 を 参 照 のこと call :ラベル 引 数 (2) 以 下 の for コマンドも 拡 張 機 能 を 有 効 にする 必 要 がある 詳 しくは for /? を 参 照 43
のこと -----^ for /d % 変 数 in (セット) do コマンド [コマンドパラメータ] セットがワイルドカードを 含 む 場 合 は ファイル 名 ではなくディレクトリ 名 の 一 致 を 指 定 します for /r [[ドライブ:]パス] % 変 数 in (セット) do コマンド [コマンドパラメータ] [ドライブ:]パスから 始 めて ツリーの 各 ディレクトリで for 文 を 実 行 し ます /r の 後 にディレクトリが 指 定 されていない 場 合 は 現 在 の ディレクトリが 使 用 されます セットが 単 一 のピリオド (.) である 場 合 は ディレクトリ ツリーの 列 挙 だけを 行 います -----$ 以 上 ( 投 稿 : 2012 年 2 月 5 日 ) 44
覚 醒 と 進 化 試 論 II フレームワーク jscripter 1.DesktopWeb フレームワーク さて 問 題 は 何 か 最 近 Google が Desktop から 撤 退 して デスクトップは 真 空 地 帯 と なっている 僕 は Google Desktop が 出 たときに これはヤバイと 考 えたものだ しか し デスクトップの 検 索 ツールから 大 きく 発 展 することはなかったので 我 らの 仕 事 は 今 のところ 安 泰 である 現 在 では デスクトップや Web の 情 報 整 理 ツールは evernote などのクラウド アプリ に 委 ねられている 似 たようなツールは 溢 れているが 今 のところ 満 足 ができるような 状 況 には 至 っていないように 思 う 単 なる 収 集 整 理 スクラップ 検 索 のためのツールでは 知 的 生 産 のためには 足 りない 自 らが 産 み 出 す 情 報 と 合 わせて 編 集 できることが 必 要 だ ろう 自 分 が 今 やっていることを Web アプリケーションにまとめることができるだろうか そ んなことを 長 い 間 漠 と 考 えてきたが もう 少 し 具 体 的 にしたい それを DesktopWeb フ レームワークと 呼 ぶことにした 実 体 が 今 のところないが 少 しずつ 作 っていこう 試 論 I で 述 べた 様 々なシステムをモジュール 化 して 統 合 したフレームワークとして 発 展 させ ることが 目 的 である 2. 小 さな 一 歩 ^^;) デスクトップ CGI が 動 作 する PC の IP アドレスを 得 る もちろん モジュールを 書 いたことはあるけど フレームワークを 作 るところまで 考 え たことはなかった それでも まずはモジュールづくりの 復 習 から デスクトップ CGI は 主 にインターネットに 接 続 する 個 人 の 小 さなネットワーク 上 で 動 作 することを 想 定 している そのような 場 合 デスクトップ CGI が 動 作 するサーバーの IP アドレスは DHCP(Dynamic Host Configuration Protocol)で 得 られることが 多 いだろう この 場 合 サーバーに 他 の PC やタブレットなどからアクセスしたい 場 合 もある が デスクトップ CGI に 埋 め 込 まれる 別 の 機 能 を 持 つデスクトップ CGI の URL のホスト 名 は localhost では 動 かない IP アドレスで 直 に 記 述 しておく 必 要 がある しかしながら こ れを 変 数 として 取 り 扱 えるようにしておかないと 環 境 が 変 化 した 場 合 にスクリプトの 該 当 箇 所 をすべて 書 きなおす 必 要 が 出 てくる これは 避 けたい 変 数 にしておくのはよいが CGI 実 行 時 の 値 を 取 得 するモジュールを 準 備 する 必 要 があ る Zazel さんに 相 談 に 乗 ってもらって いろいろと 検 討 していて 思 いついたのが ping をコンピュータ 名 を 指 定 して 実 行 する 方 法 である ping -n 1 $computername 45
と 実 行 する -n オプションは ping する 回 数 を 指 定 する コンピュータ 名 は 環 境 変 数 COM- PUTERNAME から 取 得 する この 方 法 は Windows PC だけしか 使 えないと 思 われるので その 他 のマシンで 動 作 させる 場 合 には 他 の 方 法 も 検 討 する 必 要 があるだろう さて モジュール ping2ip.pm は 次 のようである package DesktopWeb::ping2ip; require Exporter; our @ISA = qw(exporter); our @EXPORT = qw(ping2ip); our $VERSION = 0.01; sub ping2ip my ($computername) = @_; unless($computername) $computername = $ENV'COMPUTERNAME'; my $ip = "can't detect.\n"; my @pingstr = `ping -n 1 $computername`; foreach (@pingstr) if(/(\d1,3\.\d1,3\.\d1,3\.\d1,3)/) $ip = $1; last; return $ip; 1; モジュールを 使 ってみよう スクリプト 名 を ping2ip.pl としよう use DesktopWeb::ping2ip; print ping2ip; 実 行 する 46
C:\>perl ping2ip.pl 192.168.0.15 うまく 動 く 3. 次 の 一 歩 次 は デスクトップの 情 報 について 考 えてみたい 情 報 の 種 類 発 生 の 仕 方 格 納 場 所 などによって インターフェース 表 現 を 考 える 必 要 がある それをモジュール 群 としてま とめ 直 す 現 在 のブラウザ 上 のデスクトップは HTML の FRAME をインターフェースとして 使 ってい る この 方 法 は ipad などのモバイルデバイスには 向 かない 少 し 研 究 して 試 行 錯 誤 する 必 要 があるだろう ( 投 稿 : 2012 年 2 月 6 日 ) 47
編 集 後 記 jscripter 予 想 外 にみなさんの 投 稿 をいただいて 今 号 は 大 変 うれしかった ハッカーが 世 の 中 を 動 かす 時 代 という 僕 らも Web で 何 か 新 しいサービスを 生 み 出 せれ ばと 考 えたりしている 客 観 的 に 見 て 個 人 の 能 力 は 限 りなく 増 大 しつつある それは コンピュータとインターネットがもたらしたものである DesktopWeb フレームワークがそれを 現 実 のものとするようにしていきたい と ここ で 小 さな 声 で 宣 言 しておこう 以 上 ( 投 稿 : 2012 年 2 月 5 日 ) 48
TSNETスクリプト 通 信 ISSN 1884-2798 出 版 地 : 広 島 市 2012 年 2 月 6 日 4.3.001 版 2012 年 2 月 7 日 4.3.002 版 2012 年 2 月 9 日 刊 行 4.3.003 版 投 稿 規 程 TSNETWiki : 投 稿 規 程 のページを 参 照 のこと 編 集 委 員 会 ( 投 稿 順 ) Yさ でび ムムリク 機 械 伯 爵 jscripter saw[at]s7[dot]wh[dot]qit[dot]ne[dot]jp davi-1984[at]nifty[dot]com qublilabo[at]gmail[dot]com kikwai[at]livedoor[dot]com jscripter9[at]gmail[dot]com 著 作 権 1. 各 記 事 及 びその 他 の 著 作 物 については 著 作 者 が 著 作 権 を 保 持 します 2. TSNET スクリプト 通 信 の 二 次 著 作 権 は 各 記 事 及 びその 他 の 著 作 物 の 著 作 者 より 構 成 される 編 集 委 員 会 が 保 持 します 使 用 許 諾 配 布 条 件 1. 編 集 委 員 会 は TSNET スクリプト 通 信 4.3.xxx 版 を ファイル 名 が tsc_4.3.xxx.pdf の PDF ファイルとして 無 償 で 配 布 します また ファイル 名 ファイル 内 容 を 一 切 改 変 しない 状 態 での 電 子 的 再 配 布 および 印 刷 による 再 配 布 を 無 償 で 許 諾 します 2. 関 連 するスクリプトファイルなどのプログラムについては 使 用 および 再 配 布 を 無 償 で 許 諾 し ますが 改 変 後 の 再 配 布 についてはオリジナルの 著 作 権 を 併 記 することを 条 件 に 無 償 で 許 諾 し ます 3. 記 事 およびスクリプトファイルなどのプログラムに 著 作 者 の 使 用 許 諾 配 布 条 件 の 記 載 がある 場 合 は 著 作 権 の 項 および 上 記 2 項 に 優 先 するものとします 免 責 事 項 TSNET スクリプト 通 信 の 内 容 および 同 時 に 配 布 されるスクリプトなどの 使 用 は すべて 使 用 者 の 自 己 責 任 によるものとし 使 用 によって 生 ずる 一 切 の 結 果 等 について 編 集 委 員 会 および 著 作 者 は 責 任 を 負 いません 編 集 ソフトウェア OpenOffice.org 3.2.1 Writer 発 行 所 一 次 配 布 所 : TSNET スクリプト 通 信 刊 行 リスト http://text.world.coocan.jp/tsnet/?tsnet%e3%82%b9%e3%82%af%e3%83%aa %E3%83%97%E3%83%88%E9%80%9A%E4%BF%A1%E5%88%8A%E8%A1%8C%E3%83%AA%E3%82%B9%E3%83%88 49
TSNET スクリプト 通 信 第 4 巻 第 3 号 ( 通 算 第 15 号 ) 発 行 : TSC 編 集 委 員 会 発 行 日 : 2012 年 2 月 9 日 ISSN: 1884-2798 出 版 地 : 広 島 市 創 刊 : 2008 年 5 月 7 日 50