Bash
UNIX

perlとかを使ったbashプログラミング


Bashコマンドについて

よくなんかパッケージなどをインストールするとき、自動でperlとかcurlあたりのコマンドがめちゃくちゃ高速で走りますよね。

あれって「なんかすごいことやってるけどナンダコレ」って人が多いと思うんですよね。

やっぱコードを書く人間としてそこらへんに対しても理解はしておくべきという謎の義務感も感じてるわけです。

で、それの第一歩として、まずはBashの文法とかを理解しようという結論に至ったわけです。

この記事はそこらへんのまとめみたいなものです。


はじめに

「コードを書こう!」ってなった時、よく使う言語としてPythonとかRuby、Javaとかがありますよね。

で、あまり最近はあんま注目されない言語なんだけどPerlという言語があります。

Wikipediaの説明には


Perl(パール)とは、ラリー・ウォールによって開発されたプログラミング言語である。実用性と多様性を重視しており、C言語やsed、awk、シェルスクリプトなど他のプログラミング言語の優れた機能を取り入れている。ウェブ・アプリケーション、システム管理、テキスト処理などのプログラムを書くのに広く用いられている。

言語処理系としてのperlはフリーソフトウェアである。Artistic LicenseおよびGPLのもとで配布されており、誰でもどちらかのライセンスを選択して利用することができる。UNIXやWindowsなど多くのプラットフォーム上で動作する。


とまあ、こんな感じの説明がありますね。

要するに、正規表現を使ってバンバンテキスト処理しちゃうぜって言語です。

で、このperlなんですけど、Bashとめちゃくちゃ相性がいいんです。

以下ではどう相性がいいのかについて説明します。


環境

ぼくの環境は

MacBook Air early 2015で、

OSはmacOS High Sierra ver 10.13.5です。

Screen Shot 2018-06-11 at 15.03.56.png

以下でのBashのコマンドはmacの中に標準搭載しているターミナルを使います。


Perlコマンドの使用

まずはプログラミング言語の最初ということで、まずは世界にこんにちはしておきましょう。

perl -e 'print "Hello, World!\n"'

これをコマンドで叩きます。

そうすると以下のようになりますね。

Screen Shot 2018-06-11 at 15.07.31.png

おめでとうございます。

これで世界にこんにちはできました!

あなたもBashプログラマーの仲間入りです!

このコマンドの説明をすると、普通にperlコマンドを叩くとhoge.perlみたいなperlのソースコードに対して処理をさせるわけですが、-eというオプションをつけることでbash上でそのまま処理を行わさせることができるんです。

単純にbashの画面に出力させるだけなら

echo 'Fuck Kyoto Univ.'

でもいけます。

perlの文法として、文字列の連結や反復が可能で、文字列の連結は.で行えます。

print '"A"."B"'

とすれば、

Screen Shot 2018-06-11 at 16.29.19.png

というように連結ができています。

反復については文字列 x10とすれば10会の反復ができます。

perl -e 'print "A"x10 . "B\n"'

とすることで

Screen Shot 2018-06-11 at 16.31.07.png

というようにできます。素晴らしいですね。

で、さらにスゴいことが以下のコマンドがbash上では有効なことです。

$(perl -e 'print "pwd"')

これを実行すると以下の通りになります。

Screen Shot 2018-06-11 at 15.13.54.png

何が起きたかわかりますか?

bash上で叩けるコマンドでpwdは誰もが知る簡単なコマンドで、カレントディレクトリのパスを表示するコマンドですよね。

perlコマンドを叩く際に$(hogehoge)というように$マークをつけて丸括弧で囲むだけでbash上でprintしていた文字列を実行させることができるんです!!

これがわかったところで、ちょっと黒魔術っぽいコマンドをやってみましょう。

p$(perl -e 'print "w"')d

実行すると以下の通りです。

Screen Shot 2018-06-11 at 15.18.23.png

これは何をやっているかというと、pwdというコマンドを分離して、"w"という文字列だけperlコマンドで実行させたわけなんです。

なんとも変態的なコマンドです。

めっちゃキモい性質やなーって思いますが、実を言うとこの性質はハッカーにとっては非常に重宝するものであります。

例えば、

./a.out password 

というように何か引数としてパスワード要求する実行ファイルがあったとき

./a.out $(perl -e "A"x20)

というようなコマンドによってメモリのオフセットを特定したりバッファオーバーフローを引き起こして管理者権限の奪取などを行えます。

bashハックについては需要があればまた別途で書かせていただきます。

ひとまずこれについてはスルーで。


for文みたいなやつ

bashプログラミングと銘打っておいてprintだけで終わりにするわけにはいきませんよね。

プログラミング言語を扱うとき、絶対に遭遇する文法としてfor文があります。

ということでprintの次にbashにはfor文みたいなやつを紹介します。

まずfor文を紹介する前に数字の配列を生成するseqというコマンドから。

seq 1 10

これを実行すると以下の通りになります。

Screen Shot 2018-06-11 at 15.30.23.png

次に

seq 1 3 8

とすると、1から8までの数字の列を3ずつ刻みます。

Screen Shot 2018-06-11 at 15.32.27.png

これを用いた上でfor文をやってみます。

for i in $(seq 1 5); do echo 'The number is : '$i; done

とすると以下の通りになります。

Screen Shot 2018-06-11 at 15.40.08.png

for文の記述をした後、処理内容を;do ~~~で記述し、最後に;doneで締めくくることでbash上でコマンドを叩くことができます。

ちなみにこのfor文は以下の通りにも書くことができます。

for a in $(seq 1 5)

> do
> echo 'The number is : '$I
> done

こっちの方が視認性が良さそうですね。

さっき学んだ書き方をすれば、

echo ~~~のところはperl -e 'print ~~~'という書き方もできますね。

流石にゴチャゴチャしすぎてるのであまりいい書き方とは思いませんが....

ちなみに、

for a in $(seq 1 10)

> do
> echo 'Hello, World'
> done

のコマンドを叩いたあと、矢印キー↑でコマンドログを見てみると

for a in $(seq 1 10); do echo 'Hello, World'; done

として表示されます。

コンピューターとしてはこっちの方が簡明というわけですね。


次にif文を

次にif文をやりましょう。


条件文

条件文は[]で挟みます。

()でもいけます。

等号は=です。

不等号について> は -gtで、< は -ltです。

gtやltはLaTeXと同じで、greater thanless thanの略です。

条件文を書く際のポイントとして[ 'A' = 'A' ]というようにスペースを入れないとエラーになるので注意してください。


やってみる

if [ 'A' = 'A' ]

> then
> echo 'Kyoto Gorira Univ.'
> fi

とします。

ifで始めたらthenで始めてfiで締めくくります。

Screen Shot 2018-06-11 at 16.01.12.png

ちゃんとできてますね。

for文と同様に、コマンドを叩いたあと、矢印キー↑でコマンドログを見てみると

for a in $(seq 1 10); then echo 'Kyoto Gorira Univ.'; fi

として表示されます。


for文とif文が揃ったので...

for文とif文が揃いましたね。

ということで、プログラマーとしてはどうしてもやらなければならない仕事があります。

fizzbuzzですね!

for i in $(seq 1 100)

> do
> if (($i % 15 == 0)); then
> echo fizzbuzz
> elif (($i % 3 == 0)); then
> echo fizz
> elif (($i % 5 == 0)); then
> echo buzz
> else
> echo $i
> fi
> done

1行形式なら

for i in $(seq 1 100) ; do if (($i % 15 == 0)); then echo fizzbuzz ; elif (($i % 3 == 0)); then echo fizz ; elif (($i % 5 == 0)); then echo buzz ; else echo $I ; fi ; done

って感じです。

うーん、キモい。


終わりに

とりあえず簡単にbashの文法とperlを用いた云々を解説しました。

よく環境構築で~/.bash_profile~~~を書き込んでください、みたいなやつがよくあるわけですよね。

なんとなくそういうのに盲目的に従うのがなんか気持ち悪いなーってずっと思ってて、ということで勉強して、この記事にまとめるに至りました。

また気が向けば、今度はcurlコマンドなどについてまとめていこうと思います。

ではお疲れ様でした!