Pythonで文字列操作やるよ!
プログラム言語「Python」を使って、プログラムで便利なことをいろいろやろうシリーズです。
退屈なことは「Pythonにやらせよう 6章 文字列操作」をとても参考にさせていただきました。
普段の単純作業をPython使って楽にやりたい!そんな気持ちを叶えてくれる素敵な書籍です。
実例が豊富でよかったです!
ぜひ、シンプルに読みたい場合はこちらの本を購入ください!
普通にやるとなかなか頭に入ってこないので空想のキャラクターの会話風にしてみました。
よろしくどうぞ。
せんぱい「どうもこんには。ガゼルさん。今日も今日とて、Pythonやってくよ!」
ガゼルさん「はい!」
せんぱい「今回はPythonで文字列を操作する方法についてみていくよ」
ガゼルさん「文字列を操作…陰謀的な!?」
せんぱい「陰謀的ではないよ!
Pythonで文字列はシングルクォート(‘)でくくる。
もしくはダブルクォート(“)でくくっても書くことができるんだ
ダブルクォートであれば、文字列の中にシングルクォートを使用することができる。」
ガゼルさん「そう、iPhoneならね?」
せんぱい「iPhone関係ない!」
エスケープ文字
せんぱい「まず、エスケープ文字について紹介するよ」
ガゼルさん「エスケープ…逃亡という意味のやつですな。ムーンチャイルドな?」
せんぱい「懐かしい!違うよ!
ほら、ただの文字として扱いたいのに、プログラム的に意味を持つ文字列が入っていると違う意味になっちゃうでしょ?
それを回避する方法だよ。」
ガゼル「そんな…方法が!?ガフ!!」
せんぱい「何で血が出るの!?
まあ、それはさておき。例えば、文字列の中でシングルクォートとダブルクォート両方使用したいときなどだね。
そのときは、はい、エスケープ文字を使用します!
エスケープ文字は文字列に追加したい文字をバックスラッシュ(\)に続けて書くよ。
すると、2文字から構成されるが通常1文字として扱われるんだ」
ガゼルさん「さておかないで…」
せんぱい「エスケープ文字として、下記の種類があるよ」
エスケープ文字の種類
エスケープ文字 | 意味 |
---|---|
\’ | シングルクォート |
\” | ダブルクォート |
\t | タブ |
\n | 改行 |
\ | バックスラッシュ |
raw文字列
せんぱい「そして、raw文字列だ!」
ガゼルさん「raw…!ジュード・ロウ!」
せんぱい「そっちのローはLawだね!」
ガゼルさん「ノーロウ…!」
せんぱい「rawは”生の”という意味。だから”生の文字列”ということだね。
‘(クォート文字)の前にrをつけるんだ。すると、どうだい?
文字列中のエスケープ文字を無視し、バックスラッシュをバックスラッシュとして扱うようになるよ。
こんな感じだね」
print(r'This is Carol\'s cat.')
↓出力結果
‘This is Carol\’s cat.’
三連クォートによる複数行文字列コメントアウト!
せんぱい「ところでガゼルさん。Pythonのコメントアウトって、#をつけるでしょ?」
ガゼルさん「つけますね」
せんぱい「それだと、複数行をコメントアウトさせるの大変じゃない…?」
ガゼルさん「大変!」
せんぱい「はい!そんなとき便利なのが三連クォートによる複数行文字列をコメントさせる方法です!」
ガゼルさん「わあ!便利!でも、お高いんでしょう?」
せんぱい「それがなんと!Pythonでは3個のシングルクォートかダブルクォートでくくって書くだけ!
三連クォートの間のタブや改行やクォートは、文字列の一部として解釈されるよ!
下記がその例です!」
"""
これはpythonにおける複数行コメントの例だよ!
pythonコードとしても正しい。そうだろう?ガゼルさん
"""
ガゼルさん「複数行文字列の内部ではPythonのブロック字下げルールは適用されないんですね!」
せんぱい「そう!よく知ってるね!ってなんだこれ!」
文字列のインデックスとスライス
せんぱい「続いては文字列のインデックスとスライスです!」
ガゼルさん「スライスって…チーズ的な?」
せんぱい「そう、スライスチーズはゆき…ってちょいちょいちょい。
また、そのスライスではあるんだけど。」
ガゼルさん「とろけるってこと?」
せんぱい「チーズ属性はそっちじゃない
文字列はリスト(配列)と同様にインデックスとスライスを適用することができるんだよ。」
がぜるさん「ほうほう。例えば?」
せんぱい「例えば、’Hello world!’という文字列をリストとみなし、次のように要素としての1文字をインデックスに対応させると下記のようになるよ。
スペースも、!などの感嘆符も文字として含まれるからね」
文字|H|e|l|l|o| |W|o|r|l|d|!|
インデックス|0|1|2|3|4|5|6|7|8|9|10|11|
spam = 'Hello World!'
spam[0]
出力結果は ‘H’
spam[4]
出力結果は ‘o’
spam[-1]
出力結果は ‘!’
spam[0:5]
出力結果は ‘Hello’
spam[:5]
出力結果は ‘Hello’
spam[6:]
出力結果は ‘world’
せんぱい「文字列をスライスしても、元の文字列は変わらないよ。
んで、ひとつの変数からスライスを取得して別の変数に格納しておくこともできるんだ」
ガゼルさん「チーズは変わっちゃうのに…」
spam = 'Hello world!'
fizz = spam[0:5]
fizz
#出力結果は 'Hellow'
spam
#出力結果は 'Hello world!'
せんぱい「fizzはspamに入った文字列の6番目まで出力するんだね!」
ガゼルさん「配列は0からはじまるからですね!」
文字列に対するinとnot in演算子
せんぱい「リストと同様に、inとnot in演算子も文字列に適用することができるんだよ」
ガゼルさん「え~あのinとnot in演算子もー!?」
せんぱい「どの!?
まあ、それはさておき2つの文字列をinやnot in演算子で評価するとTrueかFalseのブール値になるんだよ。」
ガゼルさん「へー…(モレンド)」
せんぱい「まあ、実際に見てみるとよいと思うよ!」
'Hello' in 'Hello World'
#出力結果は True
'Hello' in 'Hello'
#出力結果は True
'HELLO' in 'Hello World'
#出力結果は False
'' in 'spam'
#出力結果は True
'cats' not in 'cats and dogs'
#出力結果は False
せんぱい「その文字が含むか含まれるかでTrue(真)かFalse(偽)か返してくれるんだよ!
この式は第1の文字列が第2の文字列に含まれるかどうかを大文字・小文字を区別し正確に調べてくれるよ!」
ガゼルさん「大文字・小文字をもってしても…!」
せんぱい「何が!?」
便利な文字列メソッドー文字列を解析したり、変換したりできるよ!
せんぱい「ここからは文字を解析したり変換したりなメソッドを…」
ガゼルさん「ときにはぷかぷか笑ったり?」
せんぱい「クラムボン!」
upper()、lower()、isupper()、islower()メソッド
せんぱい「upper()は元の文字列全てを大文字で返してくれる。
lower():元の文字列全てを小文字で返してくれるんだよ」
ガゼルさん「あっぱーとろーわー!」
spam = 'Hellow world!'
spam = spam.upper()
spam
#出力結果は'HELLO WORLD!'
spam = spam.lower()
spam
# 出力結果は'hello world!'
せんぱい「これらのメソッドは元の文字列を変更せず新しい文字列を返すんだ。
元の文字列を変更する場合はupper()やlower()を呼び出した後に新しい文字列の値を変数に代入する必要があるよ」
ガゼルさん「大文字にしたものとして、それはどれで入れ直すんですね~」
せんぱい「upper()とlower()メソッドは大文字と小文字を区別しない比較をする際に便利なんだよ
ちょっと下の構文をみてみて!」
print('How are you?')
feeling = input()
if feeling.lower() == 'great':
print('I feel great too.')
else:
print('I hope the rest of your day is good')
せんぱい「このプログラムを実行すると質問が表示されるけど、greatの揺らぎとしてGREatのように入力したとしても、I feel great too.と表示するよ」
ガゼルさん「I feel great too.Me Too!」
せんぱい「急な同意!
upper()とlower()は1文字以上の全ての文字が大文字、または小文字の場合はTrueを返すんだ。
そうでなければFalseを返すよ」
spam = 'Hello world!'
spam.islower()
# 出力結果はFalse
spam.isupper()
# 出力結果はFalse
'HELLO'.isupper()
# 出力結果はTrue
'abc12345'.islower()
# 出力結果はTrue
'12345'.islower()
# 出力結果はFalse
'12345'.isupper()
# 出力結果はFalse
せんぱい「upper()とlower()メソッドは文字列を返すから、その戻り値に対して文字列メソッドを呼び出すこともできるよ」
ガゼルさん「ええ~さらに~!?」
'Hello'.upper()
# 出力結果は'HELLO'
'Hello'.upper().lower()
# 出力結果は'hello'
'Hello'.upper().lower().upper()
# 出力結果は'HELLO'
'Hello'.lower()
# 出力結果は'hello'
'HELLO'.lower().islower()
# 出力結果は True
ガゼルさん「これ…何度も何度も…意味あります!?」
せんぱい「それは言わないで…!」
isではじまる文字列メソッドシリーズ
せんぱい「はい!ここからはisではじまる文字列シリーズです!」
ガゼルさん「古今東西!?」
せんぱい「ごめん…それに耐えうるほどは無いです…」
せんぱい「 isalpha() は1文字以上の英文字だけから文字列が構成されている場合にTrueを返すよ」
ガゼルさん「アルファベットのアルファですね!」
せんぱい「 isalnum() は1文字以上の英文字か数字から構成されている場合にTrueを返すよ!」
ガゼルさん「あるなむ!英文字か数字で構成されているものが対応するんですね!」
せんぱい「isdecimal() は1文字以上の数字だけから構成されている場合にTrueを返す]
ガゼルさん「イズデシマル! This is 弟子の丸!みたいな響き!」
せんぱい「その響きいらない!
isspace() は文字列がスぺースかタブか改行されている場合にTrueを返すよ」
ガゼルさん「これは分かりやすくスペースが入ってますな!」
せんぱい「そしてそして、istitle() は 大文字から始まり、残りが全て小文字で構成されている場合にTrueを返すよ。
はい、実例です!」
'hello'.isalphe()
# Trueを返す
'hello123'.isalpha()
# Falseを返す
'hello123'.isalnum()
# Trueを返す
'hello'.isalnum()
# Trueを返す
'123'.isdecimal()
# Trueを返す
' '.isspace()
# Trueを返す
'This Is Title Case'.istitle()
# Trueを返す
'This Is Title Case 123'.istitle()
# Trueを返す
'This Is not Title Case'.istitle()
# Falseを返す
'This Is NOT Title Case Either'.istitle()
# Falseを返す
ガゼルさん「これはなんと、まあ繊細な文字列操作ができそうですな!」
せんぱい「is”X”系の文字列メソッドはユーザー入力を検証する場合に便利だよね。
例えば、下記は正しい入力が得られるまで繰り返しユーザーに年齢とパスワードを入力してもらう処理だよ」
while True:
print('年齢を入力してください:')
age = input()
if age.isdecimal():
break
print('年齢は数字で入力してください。')
while True:
print('新しいパスワードを入力してください(英数字のみ):')
password = input()
if password.isalnum():
break
print('パスワードは英数字で入力してください')
startswith()メソッドとendswith()メソッド
せんぱい「次は、文字列の中でも最初の文字と終わりの文字に関しての操作を行う方法のやつだよ!」
ガゼルさん「はじまりと終わりの物語…!」
せんぱい「無駄に壮大なサーガがはじまりそうだな!!」
ガゼルさん「伝説がはじまる…!」
せんぱい「始まらないよ!
startswith() は対象の文字列がメソッドに渡された文字列からはじまる場合にTrueを返すよ」
ガゼルさん「はじまりが合っているかどうかなんですね!」
せんぱい「endswith() は 対象の文字列がメソッドに渡された文字列でおわる場合にTrueを返すよ!」
ガゼルさん「そして終わりが合ってるかなんですね…! そして伝説は続く」
せんぱい「続かないよ! はい、その実例です!」
'Hello world!'.startswith('Hello')
# Trueを返す
'Hello world!'.startswith('world!')
# Trueを返す
\
'abc123'.startswith('abcdef')
# Falseを返す
'abc123'.endswith('12')
# Falseを返す
'Hello world!'.startswith('Hello world!')
# Trueを返す
'Hello world!'.endtswith('Hello world!')
# Trueを返す
せんぱい「とりあえず、一部だけ合っているかという点、且つ、それがどこかという点も確認する際に便利だね!」
ガゼルさん「終わりよければ全てよし的な発想ですね!」
せんぱい「**はじまりもチェックしてるけど!?」
join()とsplit()メソッド
せんぱい「ここからは文字を繋げたり、切ったりするメソッドだよ」
ガゼルさん「らずばんだりー!!」
せんぱい「よくそのネタ知ってるね!?
join() は 文字列に対して呼び出し、文字列のリストを渡すと文字列を返す。
戻り値の文字列はリストの中の文字列を連結したものになるよ。」
ガゼルさん「Join us!! 君とぼくの広がる輪♪中に空洞あいている練り物、ちくわ♪」
せんぱい「何その歌!?では実例みていくよ!!」
','.join(['cat','rats','bats'])
#出力結果は 'cat','rats','bats'!
''.join(['My','name','is','Simon'])
#出力結果は 'My name is Simon'!
'ABC'.join(['My','name','is','Simon'])
#出力結果は 'MyABCnameABCisABCSimon'!
ガゼルさん「ええ!?間に入るんですね!?
三つ目とか、間にABCが入って何が何だか。凶器のさたですよ!」
せんぱい「そこまで!?
まあ、見ての通りjoin()を呼び出す対象の文字列がリストの文字列の間に挿入されるんだよね。」
ガゼルさん「繋ぎ物をいっきに変えたいときに便利なんですね!」
せんぱい「で、split() は 文字列に対し呼び出した際、分割させた文字列のリストを返すよ。
戻り値の文字列には空白文字は含まれないよ。
実例で見てみるね」
'My name is Simon'.split()
#出力結果は 'My','name','is','Simon' となる
せんぱい「こんな感じで、区切り文字を渡すこともできるよ」
'MyABCnameABCisABCSimon'.split(ABC)
#出力結果は 'My','name','is','Simon' となる
'My','name','is','Simon'.split('m')
#出力結果は 'My na','e is Si','on' となる
ガゼルさん「mがきえた!」
せんぱい「.split()は複数行の文字列を改行文字で分割するときとかによく使用されるよ!
例えばホラ、見てみて!」
spam = '''Dear Alice,
How have you been? I am fire.
There is a container in the fridge
that is labelrd "Milk Experiment".
Please do not drink it.
Sincerely,
Bob'''
spam.split('\n')
せんぱい「出力結果はこんな風になります!」
[‘Dear Alice,’,’How have you been? I am fine.’,’There is a countainer in the fridge’,’that is labeled “Milk Experiment”.’,”,’Please do not drink it.’, Sincerely,’,’Bob’]
rjust(),ljust(),center()メソッドでテキストを揃える
せんぱい「そしてお次は、揃えるやつだよ」
ガゼルさん「揃えるやつ…妖怪ですか!?」
せんぱい「そんな妖怪っていたっけ?まず、rjust()・ljust()ね!」
- rjust()
対象の文字列にスペースを挿入し右揃えの文字列を返す -
ljust()
対象の文字列にスペースを挿入し左揃えの文字列を返す
せんぱい「実際につかってみるとこんな風になるよ!」
'Hello'.rjust(10)
#出力結果は ' Hello'
'Hello'.rjust(20)
#出力結果は ' Hello'
'Hello World'.rjust(20)
#出力結果は ' Hello World'
'Hello'.ljust(10)
#出力結果は 'Hello '
ガゼルさん「おお!文字数を渡すとその文字数の中で揃えてくれるんですね!
なんということでしょう!」
せんぱい「でで、スペース以外の文字を使って空白を埋めたい場合はオプションとしてrjust()とljust()の第2引数に指定することができるんだ!」
ガゼルさん「第2…引数??」
せんぱい「まあ、まずは見てみてよ!ほい!」
'Hello'.rjust(20, '*')
#出力結果は '***************'Hello'
'Hello'.ljust(20, '-')
#出力結果は 'Hello'---------------'
ガゼルさん「なんか…シュールですね…」
せんぱい「え…シュール!?そしては次は右での左でもない…中央揃えだ!」
ガゼルさん「右でも左でもない…!中道的な!?」
せんぱい「思想の位置!!」
- center()
左右揃えではなく、中央揃えを行う。
せんぱい「はい、では実際に見てみよう!」
'Hello'.center(20)
#出力結果は ' Hello '
'Hello'.center(20,"=")
#出力結果は '========Hello======='
ガゼルさん「おお!真ん中にきちっと!」
せんぱい「表形式のデータを正しくスペースをあけて表示したい際に特に便利だよ
みてみて!」
def print_picnic(item_dict,left_width,right_width):
print('PICNIC ITEM'.center(left_width + right_width,'-'))
for k, v in items_dict.item():
print(k.ljust(left_width, '.') + str(v).rjust(right_width))
picnic_items = {'sandwiches': 4, 'apples': 12, 'cups': 4, 'cookies':8000}
print_picnic(picnic_items, 12, 5)
print_picnic(picnic_items, 20, 6)
出力結果は下記のようになる。
---PICNIC ITEMS---
sandwiches.. 4
apples...... 12
cups........ 4
cookies..... 8000
-------PICNIC ITEMS-------
sandwiches.......... 4
apples.............. 12
cups................ 4
cookies............. 8000
ガゼルさん「おお!なんかガシッと揃っとるやないかい!」
せんぱい「こんな感じでrjust()、ljust()、center()を用いると、文字列の長さが分からなくても文字列をきれいに揃えることができるんだよ」
ガゼルさん「おお!それとなく揃える際に便利そうですね!」
せんぱい「(…それとなく揃えるときってどんなときだろう?)」
strip()、rstrip()、lstrip()メソッドで空白を除去
せんぱい「今度は空白を除く、strip()メソッドだ!」
ガゼルさん「ストリップ…!脱ぐというか、除くんですね」
せんぱい「そう、除くんだ」
ガゼルさん「ぼく…いつかストリップショーに出たいと思っています」
せんぱい「なにその無駄な大胆発言。
まあ、ひとまずstrip()メソッドはこんな種類があるよ」
- strip()
文字列の冒頭と末尾の空白文字を除去した文字列を返すよ -
rstrip()
文字列の末尾の空白文字を除去した文字列を返すよ。
rだからrightで右ということだね! -
lstrip()\
文字列の冒頭の空白文字を除去した文字列を返すよ。
lだからleftで左ってことだね!
せんぱい「これらの実例だよ」
spam = ' Hello World '
spam.strip()
# 出力結果は 'Hello World'
spam.ltrip()
# 出力結果は 'Hello World '
spam.rtrip()
# 出力結果は ' Hello World'
ガゼルさん「ほんとだ!右に行ったり左にいったり!」
spam = 'SpamSpamBsconSpamEggsSpamSpam'
spam.strip('amps')
# 出力結果は 'BaconSpamEggs'
せんぱい「split()は空白を削除するだけではないよ!
オプションとして除去すべき文字を文字の引数として渡すことでその文字を除去してくれるよ!」
ガゼルさん「すごい!消し去る者みたい!」
せんぱい「誰それ!?split()メソッドみたいな人いるの!?
strip()に渡す文字列は、文字の並び順は任意なんだ。
どんな順番で渡しても、それぞれ文字が除去されるよ!」
peperclipモジュールを用いて文字列をコピー&ペースト!
せんぱい「ガゼルさんはペーパークリックは知ってる?」
ガゼルさん「ペーパークリップって、あのペーパークリップ?神を止めるやつ?」
せんぱい「かみ違いになってるよ。なんだかとてつもないことをやろうとする雰囲気がしちゃっているよ。
ペーパークリップはpeperclip、紙を止めるほうだね」
ガゼルさん「ああ、そっち」
せんぱい「普通こっちだよ。
で、その普通のペーパークリップのモジュールにはcopy()とpaste()という関数があってね」
これらのメソッドは、コンピューターのクリップボードとテキストを授受することができるんだよ」
ガゼルさん「…念力!?」
せんぱい「いや、同じコンピューターだからね」
peperclipモジュールはPythonに同封されていない。
サードパーティー製のモジュールだから別途インストールする必要があるよ」
ガゼルさん「サードパーティー製…第三勢力群として慎重に見極める必要がありますね」
せんぱい「なんの話!?よく分からないけれどちょっと実例をみてみるよ。
たとえば、“ガゼルさんはコーヒーが好き”というテキストをコピーしてから下記を実行してみると」
import pyperclip
pyperclip.paste()
‘ガゼルさんはコーヒーが好き’
せんぱい「みたいになるんだ!」
‘ぼくはストリップダンサーになりたい’
ガゼルさん「ほんとだ!」
せんぱい「なんでよ!
そして、こんな感じで他のプログラムがクリップボードの内容を書き換えるともちろん、paste()関数はその内容を返すよ」
import pyperclip
pyperclip.copy('Hello World!')
pyperclip.paste()
#出力結果は 'Hello world!'
これまでの出てきなものを活かしてパスワードロッカーを作成してみよう!
せんぱい「はい、これまで出てきた文字列を操作するあれこれで、パスワードロッカーを作成してみよう!のコーナーです!」
ガゼルさん「パスワードロッカー?」
せんぱい「そう!いろんなガゼルさんもいろんなWebサイトにアカウントをもっているでしょ?」
ガゼルさん「そうですね!サバンニング・ドットコムとか、サバゾンとか」
せんぱい「なんだかとても気になるサイト名ばかりだね!
それらのサイトで同じパスワード使いまわしてない?」
ガゼルさん「ぎく!ぎくー!なぜそれを!?」
せんぱい「使いまわしているの!?
ほら、それは危険だよね。どこかのサイトが侵入され、パスワードを盗まれると他のサイトにも侵入されちゃうでしょ?」
ガゼルさん「そ、そうですね!少しでも安全性を高めるために1024bitのパスワードに変更します!」
せんぱい「128文字!はさすがに長いよ!はい、そんなときの、パスワードロッカーなんです!」
ガゼルさん「ええ!?ここで例の彼が!?」
せんぱい「彼ではないけどね。パスワードロッカーはまあ、言うなればパスワード管理ツールみたいなものだね!
1つのマスターパスワードを使用し、解除して管理するんだよ」
ガゼルさん「ほんと、パスワードのロッカーみたいな感じなんですね」
せんぱい「はい!そのロッカーをあけるといろんなサイトのパスワードが表示されているので、必要なパスワードを取り出して使用するってわけだね~」
ガゼルさん「ずらっとですね」
せんぱい「これから試しに作成するのはマスターパスワードで暗号化していないから、セキュリティー的には脆弱だけど、基本的なプログラムの働きをイメージできるよ。まあ、まずはお試しってことで!」
#! python3
# pw.py - パスワード管理プログラム(脆弱性あり!)
PASSWORDS = {'email':'EnwaYW+-dqpF',
'blog':'as)urh3mgZ!A',
'luggaea':'12345',}
import sys
import pyperclip
if len(sys.argv) < 2:
print('使い方: python pw.py [アカウント名]')
print('パスワードをクリップボードにコピーします')
sys.exit()
account = sys.argv[1] #最初のコマンドライン引数がアカウント名
if accout in PASSWORDS:
pyperclip.copy(PASSWORD[account])
print(account + 'のパスワードをクリップボードにコピーしました')
else :
print(account + 'というアカウント名はありません')
せんぱい「プログラムはざっとこんな感じです。それぞれ、手順にそって説明していくね」
ガゼルさん「は~い!」
せんぱい「上のプログラムは、ブログなどの各サービスのアカウント名をコマンドライン引数として指定できるように作成する。
こうすることで、今回作成するプログラムではクリップボードに貼り付けられたアカウントを受け取って、それを更にまたクリップボードに貼り付けてくれるんだ。」
ガゼルさん「ええ…魔法!?」
せんぱい「ね、便利でしょ?んで、あとはパスワードのところにペーストすればよい
じゃあ、上記のプログラムを手順に沿って説明していくよ!
まず、新たにファイルエディタを開きますと。そして、プログラムをpw.pyという名前で保存する、と」
ガゼルさん「さいしょの #! というのは?#ってコメントアウトですよね?」
せんぱい「それはね、シバン(shebang)といって、このスクリプトを実行するのはPythonであることをコンピューターに伝える働きをしてくれるんだよ。
シバン行は#!ではじめるけど、その書き方はOSに依存するんだ。それぞれ、」
- windows
#! python3
- Mac
#! /usr/bin/env python3
- Linux
#! /usr/bin/python3
せんぱい「てな感じだね。コマンドラインからプログラムを実行する際に必要になるんだよ。
実行方法の詳細についてはまたおってだね~
で!肝心のプログラムなんだけど」
PASSWORDS = {'email':'EnwaYW+-dqpF',
'blog':'as)urh3mgZ!A',
'luggaea':'12345',}
せんぱい「まず、アカウント名とパスワードを関連づけるために辞書の中に文字列として記載するんだよ。
言い換えると、辞書がアカウント名とパスワードを関連づけるデータ構造になるわけだね」
ガゼルさん「とにかくIDとパスワードを紐づける必要があるんですね~」
せんぱい「そうそう!」
import sys
import pyperclip
if len(sys.argv) < 2:
print('使い方: python pw.py [アカウント名]')
print('パスワードをクリップボードにコピーします')
sys.exit()
account = sys.argv[1] #最初のコマンドライン引数がアカウント名(リストでいうと2番目)
せんぱい「まず、コマンドライン引数は sys.argv という変数に格納されるんだ。
これは、importしておいた、sysモジュールの、argvモジュールということだね。
」
ガゼルさん「モジュールで、モジュール!」
せんぱい「sys.argvの最初の要素は常にプログラムのファイル名 pw.pyを含んだ文字列になるんだ。
2番目の要素以降がコマンドライン引数になるよ」
ガゼルさん「とりあえず、最初はプログラム名がくるんですね!」
せんぱい「そしてそして、この、プログラムではパスワードを知りたいアカウント名を引数で指定するでしょ?
コマンドライン引数は必ず必要になるから、もし、ユーザーが引数をつけ忘れたとき、ここではリスト・sys.argvの長さが2未満のときはこのプログラムの使用方法を表示するようにしてるんだね」
ガゼルさん「リスト(list型) をlen()の引数に指定するとその要素数を取得できるんでしたっけ?
つまり、1つしかない場合ってクリップボードに何もコピーされていないってことですね?」
せんぱい「そうそう!だから、ユーザーがクリップボードにコピーし忘れた場合には使用方法を教えるメッセージを出すんだ
んで、一旦はプログラムを終了する、と」
ガゼルさん「その場合、’パスワードをクリップボードにコピーします’ と表示されるということですね!」
せんぱい「無事、リストが2以上だったらクリップボードの値を 変数account に格納できるってわけ。
そして、変数accountにアカウント名が文字列として保存できたら、辞書PASSWORDSのキーとして存在するか調べるんだ」
ガゼルさん「存在していた場合、pyperclip.copy()を用いてそのキーの値をクリップボードにコピーするわけですね!」
せんぱい「変数accountを使用せずにアカウント名が必要なところでsys.argv[1]を使用するようにしてもいいけれど、sys.argv[1]よりはaccountという変数名のほうがぐっと読みやすくなる。そんな思いやり…大事…」
ガゼルさん「やさしい世界…!」
account = sys.argv[1] #最初のコマンドライン引数がアカウント名
if accout in PASSWORDS:
pyperclip.copy(PASSWORD[account])
print(account + 'のパスワードをクリップボードにコピーしました')
else :
print(account + 'というアカウント名はありません')
せんぱい「上記の部分は辞書PASSWORDからアカウント名を探すよ。
もし、アカウント名が辞書のキーに含まれていれば対応する値をクリップボードにコピーし、その旨を表示する」
ガゼルさん「んで、含まれていない場合はアカウント名がないというメッセージを表示すると」
せんぱい「そう!これでまず簡易版のプログラムは完成です!」
ガゼルさん「おお~!ざっとこのプログラムはこんな流れってことですね!」
あるサービスにログインしたい!
↓
IDをコピー!
↓
パスワードロッカーのプログラムを呼び出し!
↓
パスワードがクリップボードにコピーされる!
↓
ログインするとき使用すればいい!
せんぱい「ちょっと前に触れたみたいに、バッチファイルとして作成しておくとWindowsだとWin-Rキーでファイル名を指定し実行することができるよ。そうすることでいつでもすぐ呼び出せる!」
ガゼルさん「パシリみたいですね。バッチ…はいる?」
せんぱい「パシリはそんなすぐ来れないでしょ…それになんでファイルが要る?みていな感じになってるの?
バッチファイルは処理をかいておいて、呼び出すことでいつでも処理を実行できるようにしておけるファイルのことだね!」
ガゼルさん「へへ~なんか便利そう!」
せんぱい「便利そうでしょ?例えば、今回作成したファイルを呼び出すために下記のように記述してpw.batというファイル名をつけてC:\Windowsフォルダに保存してみるとするでしょ」
@py.exe C:\Python36\pw.py %*
@pause
せんぱい「まあ、C:\Python36\pw.py の部分は使用しているPythonのバージョンなど自身の環境に合わせてpw.pyのフルパスを記述する必要があるからね!」
ガゼルさん「フルパス~!」
せんぱい「なんでIKKOさん風に!?」
Wikiで箇条書きするプログラムをつくってみよう!
せんぱい「お次はwikiで箇条書きできるプログラムだよ!
このプログラムを実行すると、クリップボードに保存したテキストの各行に*を追加して、箇条書きにしてくれるよ!」
ガゼルさん「先頭に*をふってくれるんですね。
なんてフェチな処理!フェチ処理!」
せんぱい「・・・・」
#! python3
# bulletPointAdder - クリップポードのテキストの各行に点をうって、wikipediaの箇条書きにする
import pyperclip
text = pyperclip.paste()
#TODO: 行を分割して、'*'を追加する
lines = text.split('\n')
for i in range(len(lines)): #"lines"リストの各要素をループする
lines[i] = '* ' + lines[i]#"lines"の要素に"*"を追加する
text = '\n'.join(lines)
pyperclip.copy(text)
ガゼルさん「この処理を実行すると」
ガゼル
パデル
ハデル
ハデス
ガゼルさん「が、」
*ガゼル
*パデル
*ハデル
*ハデス
ガゼルさん「となった!」
せんぱい「なにこの単語!?
まず、このプログラムを bulletPointAdder.py として保存しよう。
このプログラムは下記の処理を行うを行う必要があるよね」
1.クリップボードからテキストを取得する
2.テキスト処理をする
3.新しいテキストをクリップボードにコピーする
せんぱい「2番目の処理は若干ややこしいけど、さいしょと3番目の処理はごく単純。
それぞれ、peperclip.paste()とpyperclip.copy()を呼び出すだけ。
それぞれの処理だけを記述すると」
#! python3
# bulletPointAdder.py - クリップポードのテキストの各行に点をうって、wikipediaの箇条書きにする
import pyperclip
text = pyperclip.paste()
#TODO: 行を分割して、'*'を追加するよ
pyperclip.copy(text)
せんぱい「peperclip.paste()は、クリップボードのテキストをひとつの長い文字列として返すでしょ?
さっきの例では」
‘ガゼル\nパデル\nハデル\nハデス’
せんぱい「こんなテキストが返ってくるわけだね」
ガゼルさん「文字列中の\nって改行文字でしたっけ?」
せんぱい「そうそう!複数行にわたり表示する為に必要なものだね!
今だと、ひとつの文字列の中に4つの“行”が含まれていることを意味するわけだね」
ガゼルさん「4つの業…!」
せんぱい「行ね。なんか4つの罪があるみたいになってるよ!?
で、この各行の先頭に*を追加したいわけでしょ?」
ガゼルさん「はいーーーー!」
せんぱい「急にすごいいい返事!!
それには改行文字\nを検索してを追加するコードを書いてもいいけど、ここではsplit()メソッドを使用する
元の文字列を各行に分割した文字列のリストを取得して、それからそのリストの各要素の先頭にをつけるんだ」
ガゼルさん「しょうがないですねぇ、じゃあそれで」
せんぱい「え?なんでしょうがなくみたいな感じになってるの!?」
lines = text.split('\n')
for i in range(len(lines)): #"lines"リストの各要素をループする
lines[i] = '* ' + lines[i]#"lines"の要素に"*"を追加する
pyperclip.copy(text)
せんぱい「テキストを改行文字で分割すると、テキストの各行を要素としたリストを取得できるでしょ?」
このリストをlinesという変数に保存して、その各要素をループし、たどると」
ガゼルさん「range()にlen(lines)を入れてチンしているんですね~」
せんぱい「range()はrengeでみてみるといいよ!Python2とPython3で扱いが違うから気を付けてね~
まあ、linesのリストの数だけfor文を回しているんだね~」
ガゼルさん「そんな風に回して、各行に*を追加することができるというわけですね!」
せんぱい「そうそう!pyperclip.copy()は文字列のリストではなく、ひとつの文字列の値を引数にとるんだ
そこで、join()メソッドを使用し、文字列のリストをひとつの文字列にまとめるよ!」
text = '\n'.join(lines)
せんぱい「はい、これでまたこのプログラムの出来上がり、と」
ガゼルさん「これで、さっきのハデスが出来上がるんですね♪」
せんぱい「だからなんでさっきの単語並べたいの!?何でハデス!?まあ、これらの処理は箇条書きみたいな特別な作業に限らず、各行の末尾の空白文字を削除したり、テキストを大文字化・小文字化するなどしてテキスト処理を自動化したりすると面白いかもね!」
文字列操作の章を振り返って
せんぱい「これまでいろいろ文字列を操作するあれこれみてきたけれど、どうでした?」
ガゼルさん「う~ん、地味?」
せんぱい「まっすぐな感想!
でも、地味だからこそ使いこなすと普段のめんどくさい作業を楽にしてくれることうけあいだよ!」
ガゼルさん「へ~」
せんぱい「処理したい文字列をコピーして、バッチファイルを呼び出して実行とかすると、ホラ!
なんか仕事ができる人っぽい!」
せんぱい「たとえば、print()でテキストを表示したり、input()でテキストを入力する方法と比べてクリップボードを使用するともっと大量のテキストを入出力することが可能となるよね。地味だけど、便利でしょ?」
ガゼルさん「確かに、小さいけれど、積み重ねると大きいですね」
せんぱい「あと、Pythonでいろいろやろうとすると、やっぱり知識が足りないように感じるかもしれない。」
ガゼルさん「はい、やりたいことをやろうとすると、まだまだ勉強しなきゃ!と思います」
せんぱい「安心してください!佩いてます(太刀を腰に佩くのように使用する、の意)」
ガゼルさん「なんか聞いたことある響き!」
せんぱい「そんなときこそ、Pythonのモジュールを活用してみて!他のプログラマーが作った知恵を存分に借りまくるとよいよ!」
ガゼルさん「はい!!モジュモジュしてみますー!」
せんぱい「今回の内容は下記をとても参考にさせてもらいました!興味をもっていただいたらこちらもぜひー!」