Pythonワンライナーで解く『シェル・ワンライナー160本ノック』第1章(問題1から問題11まで)
はじめに
この記事では、書籍『シェル・ワンライナー160本ノック』の問題をPythonワンライナーで解いてみます。シェル芸もPythonも素人ではありますが、精一杯取り組んでいきますので、何卒よろしくお願いいたします。今回は第1章の問題を解きます。
対象読者
シェル芸とPythonを愛する人々に読んでいただけますと幸いです。
注意
私のPythonワンライナーが正しい保証はありませんので、ご注意くださいませ。
書籍情報
書籍『シェル・ワンライナー160本ノック』のページです。
書籍『シェル・ワンライナー160本ノック』のGitHubのページです。参考記事
Pythonワンライナーの記事です。参考にさせていただきました。ありがとうございます。
問題1
それでは、さっそくPythonワンライナーで問題を解いていきます。まず、a=open("files.txt","r");b=a.readlines();a.close();
でファイルの内容を読み込みます。次に、b=[re.findall(".*\.exe$",c) for c in b];
でexeファイルだけを抜き出します。そして、最後に、[print(c[0]) for c in b if c]
で出力します。
python3 -c 'import re;a=open("files.txt","r");b=a.readlines();a.close();b=[re.findall(".*\.exe$",c) for c in b];[print(c[0]) for c in b if c]'
ファイルの読み込みについて、こちらの記事を参考にさせていただきました。ありがとうございます。
文字列の検索方法について、こちらの記事を参考にさせていただきました。ありがとうございます。 Pythonの正規表現について、こちらの記事を参考にさせていただきました。ありがとうございます。 リストの内包表記でif文を使う方法について、こちらの記事を参考にさせていただきました。ありがとうございます。問題2
次は画像変換の問題です。まずa=glob.glob("*.png")
で画像のファイルパスを取得します。次にb=[b[:-3]+"jpg" for b in a]
で変換後のファイルパスを生成します。そして、c=[Image.open(c) for c in a]
で画像を開き、c=[d.convert("RGB") for d in c]
で変換して、[c[d].save(b[d],"JPEG") for d in range(len(c))]
で保存します。
python3 -c 'import glob;from PIL import Image;a=glob.glob("*.png");b=[b[:-3]+"jpg" for b in a];c=[Image.open(c) for c in a];c=[d.convert("RGB") for d in c];[c[d].save(b[d],"JPEG") for d in range(len(c))]'
Pillowの使い方について、こちらの記事を参考にさせていただきました。ありがとうございます。
問題3
次はファイル名の変更を行う問題です。まずa=glob.glob("*")
でファイルパスを取得します。その後、a[b].zfill(7)
でファイル名の0埋めをしつつ、os.rename(a[b],a[b].zfill(7))
でファイル名を変更しています。
python3 -c 'import os,glob;a=glob.glob("*");[os.rename(a[b],a[b].zfill(7)) for b in range(len(a))]'
文字列の0埋めについて、こちらの記事を参考にさせていただきました。ありがとうございます。
ファイル名の変更について、こちらの記事を参考にさせていただきました。ありがとうございます。問題4
次はファイル削除の問題です。exec
を使ったらもう普通のPythonですね。a=glob.glob("*")
でファイルパスを取得し、c=open(a[b],r)
でファイルを開き、if c.readline()==d:\n\t\tos.remove(a[b])
で10
に一致したファイルを削除しています。一度に開くことができるファイル数には限りがあるので、必ずc.close()
しましょう。
python3 -c 'import os,glob;a=glob.glob("*");r="r";d="10\n";exec("for b in range(len(a)):\n\tc=open(a[b],r)\n\tif c.readline()==d:\n\t\tos.remove(a[b])\n\tc.close()")'
ファイルの削除について、こちらの記事を参考にさせていただきました。ありがとうございます。
execについて、こちらの記事を参考にさせていただきました。ありがとうございます。問題5
次はファイルから情報を抽出する問題です。a=open("ntp.conf","r");b=a.readlines();a.close()
でファイルの内容を読み取ります。その後、c=[re.findall("^pool.*$",c) for c in b]
でpool
の行を抜き出し、e=[[re.findall("\s.*",e) for e in d] for d in c if d];[print(f[0][0]) for f in e]'
で出力します。
python3 -c 'import re;a=open("ntp.conf","r");b=a.readlines();a.close();c=[re.findall("^pool.*$",c) for c in b];e=[[re.findall("\s.*",e) for e in d] for d in c if d];[print(f[0][0]) for f in e]'
問題6
次は描画問題です。素直に解きます。
python3 -c 'print(" x\n x\n x\n x\n x\n")'
問題7
次は表計算の問題です。まず、Pandasを使ってa=p.read_csv("kakeibo.txt",sep=" ",header=None)
のようにスペース区切りのcsvファイルとしてデータを読み込みます。その後、b=a.values.tolist()
でリストに変換します。最後にexecの中で消費税率が10%と8%のときの場合分けをして合計の計算をしています。
python3 -c 'import pandas as p;a=p.read_csv("kakeibo.txt",sep=" ",header=None);b=a.values.tolist();c=0;e="20191001";f="*";exec("for d in b:\n\tif str(d[0])<e or d[1][0]==f:\n\t\tc+=int(d[2]*1.08)\n\telse:\n\t\tc+=int(d[2]*1.1)");print(c)'
Pandasの使い方について、こちらの記事を参考にさせていただきました。ありがとうございます。
リストへの変換について、こちらの記事を参考にさせていただきました。ありがとうございます。問題8
次はログファイルの集計問題です。まず、a=p.read_csv("access.log",sep=" ",header=None)
でファイルを読み込み、b=a.values.tolist()
でリストに変換します。その後、c=[c[3] for c in b];e=[re.findall(":[0-9][0-9]:",d) for d in c];f=[re.findall("[0-9][0-9]",f[0]) for f in e];
で時刻情報を抜き出します。最後にexec("for g in f:\n\tif int(g[0])<12:\n\t\th+=1\n\telse:\n\t\ti+=1");print("午前:"+str(h));print("午後:"+str(i))
で午前と午後をカウントしています。
python3 -c 'import pandas as p;import re;a=p.read_csv("access.log",sep=" ",header=None);b=a.values.tolist();c=[c[3] for c in b];e=[re.findall(":[0-9][0-9]:",d) for d in c];f=[re.findall("[0-9][0-9]",f[0]) for f in e];h=0;i=0;exec("for g in f:\n\tif int(g[0])<12:\n\t\th+=1\n\telse:\n\t\ti+=1");print("午前:"+str(h));print("午後:"+str(i))'
問題9
次もログの問題です。a=open("log_range.log","r");b=a.readlines();a.close();
でファイルの内容を読み取ります。その後、年月日+時刻情報の文字列を比較して、2016年12月24日21時台~2016年12月25日3時台までのデータだけ抜き出します。
python3 -c 'import re;a=open("log_range.log","r");b=a.readlines();a.close();d=[re.findall("""[0-9][0-9]/Dec/2016 [0-9][0-9]:[0-9][0-9]:[0-9][0-9]""",d) for d in b];[print(b[e]) for e in range(len(b)) if d[e][0]>"""24/Dec/2016 20:59:59""" and d[e][0]<"""25/Dec/2016 04:00:00"""]'
問題10
次は置換の問題です。まずa=open("headings.md","r");b=a.readlines();a.close();
でファイルの内容を読み取ります。次にc="## ";d="# ";e="";h="---";i="===";
で置換の材料を用意します。その後、exec
において置換を行います。最後にa=open("headings.md","w");[a.write(j) for j in b];a.close()
で置換後のデータをファイルに書き込みます。
python3 -c 'import re;a=open("headings.md","r");b=a.readlines();a.close();c="## ";d="# ";e="";h="---";i="===";f=len(b);g=0;exec("while g < f:\n\tif c in b[g]:\n\t\tb[g]=re.sub(c,e,b[g]);b.insert(g+1,h);f+=1\n\telif d in b[g]:\n\t\tb[g]=re.sub(d,e,b[g]);b.insert(g+1,i);f+=1\n\tg+=1");a=open("headings.md","w");[a.write(j) for j in b];a.close()'
文字列の置換について、こちらの記事を参考にさせていただきました。ありがとうございます。
リストの挿入について、こちらの記事を参考にさせていただきました。ありがとうございます。 ファイルへの書き込みについて、こちらの記事を参考にさせていただきました。ありがとうございます。問題11
第1章の最後の問題です。まずa=open("gijiroku.txt","r");b=a.readlines();a.close();
でファイルの内容を読み込みます。次にd1="すず";d2="鈴木";e1="さと";e2="佐藤";f1="やま";f2="山田";g1="\n";g2=":";
で置換の材料を用意します。その後、exec
において置換を行います。最後に、a=open("gijiroku.txt","w");[a.write(h) for h in b];a.close()
でファイルに置換後のデータを書き込んでいます。
python3 -c 'a=open("gijiroku.txt","r");b=a.readlines();a.close();b.append("\n");d1="すず";d2="鈴木";e1="さと";e2="佐藤";f1="やま";f2="山田";g1="\n";g2=":";i=0;exec("while i < len(b):\n\tif d1 in b[i]:\n\t\tb[i]=b[i].replace(d1,d2);b[i]=b[i].replace(g1,g2);i+=2\n\tif e1 in b[i]:\n\t\tb[i]=b[i].replace(e1,e2);b[i]=b[i].replace(g1,g2);i+=2\n\tif f1 in b[i]:\n\t\tb[i]=b[i].replace(f1,f2);b[i]=b[i].replace(g1,g2);i+=2\n\ti+=1");a=open("gijiroku.txt","w");[a.write(h) for h in b];a.close()'
おわりに
すべてのシェル芸とPythonと読者の方々に感謝します。ありがとうございました。楽しかったです。
スクラップ:シェル芸とPythonワンライナー
スクラップでシェル芸とPythonワンライナーの情報をまとめています。
ブログを移行しました
続きはこちらから
Discussion