Perl Hackers Hub

第57回 自作ツールによる日常業務効率化―初歩的なコードだけで身近な問題を解決!(2)

この記事を読むのに必要な時間:およそ 5.5 分

前回の(1)こちらから。

シェルコマンドを組み合わせる

(1)では,Perlの初歩的な構文を使って作成したツールを紹介しました。⁠2)では,そこにシェルコマンドを組み合わせた例を紹介します。

openコマンドを組み合わせる

筆者は普段Macを使用していますが,Macのシェルにはopenというコマンドがあり,ターミナル操作ではこれをよく使います。

openコマンドは,引数にファイル名やURLを入れるとそれらを開いてくれます。

fooディレクトリのbar.txtをデフォルトのアプリケーションで開く

$ open foo/bar.txt

技術評論社のWebサイトをブラウザで開く

$ open https://gihyo.jp/
system関数を使う

では,このopenコマンドをPerlのコードから使うにはどうすればよいでしょうか。

Perlでシェルのコマンドを呼び出す方法はいくつかありますが,筆者は戻り値を使う場合はバッククオートを,戻り値を使わない場合はsystem関数を使っています。

今回のopenコマンドでは戻り値を使わないので,system関数で次のように書きます。

system 'open', 'https://gihyo.jp/';
複数のWebサイトを一斉に開く

では次に,これを前節で紹介したfor文,if文,__DATA__のセットと組み合わせてみましょう。

link-opener.pl

my @links = <DATA>;

for (@links) {
    if ($_ =~ /(https?:\S+)/) {
    system 'open', $1;
    }
}

__DATA__
https://gihyo.jp/
https://twitter.com/
https://www.google.co.jp/

このコードを実行すると,__DATA__の下に入れたURLのWebページが次々とブラウザで開かれます。

筆者は編集や執筆の仕事をする際,その資料として多くのURLを手もとにストックしていますが,これを一度に全部確認したいとき,ブラウザにURLを貼り付けたり,どこかにリンク集を作成して1つずつクリックしたりするのではなく,一度実行するだけですべてのURLを開けるこのコードを使います。

複数ファイルの行数や文字数をカウントする

件の音楽全集では,メインコンテンツとして毎回3万字弱の座談会記事を作成していました。しかしその素材となる文字起こしは8~10万字という膨大なものだったので,これを1本のファイル上で編集していくのではなく,まず大まかなトピックごとにファイルを分割し,それぞれのファイルで編集を行ってから1本にマージして仕上げていました。

この際,各ファイルの進捗を把握するために,それらの行数や文字数をカウントしたいと考えて作ったのが次のツールです。

line-word-count.pl

use feature 'say';

my @iter = glob "*";
my $line_sum = 0;
my $word_sum = 0;

for (@iter) {
    next if (-d "$_");
    next unless ($_ =~ /(txt|md)\z/);

    my $name = `wc -lm "$_" | awk '{ print \$NF}'`  
    my $line = `wc -lm "$_" | awk '{ print \$1}'`;  |(1)
    my $word = `wc -lm "$_" | awk '{ print \$2}'`;  

    chomp $name;
    chomp $line;
    chomp $word;

    $name =~ s/.*?\/?([^\/]+)\z/$1/;
    $word = $word - $line if $line > 1;
    $line++;
    print "$name =>\tlines: $line\twords: $word";

    $line_sum += $line;
    $word_sum += $word;
    say "";
}
say "";
say "Lines total:\t$line_sum";
say "Words total:\t$word_sum";

コードには,シェルコマンドのwcawkが含まれています(1)⁠。当初はその部分を含めて.bashrcの関数注1として書いていたのですが,その他の繰り返し処理や正規表現なども含めてすべてシェルスクリプトで書くのは自分には難しいと判断し,それら周辺的な部分はPerlで書くことにしました。

使い方

では,使ってみましょう。なるべく手軽に使えるように,ここではlwcというエイリアスを設定しておきます。

.bashrc

alias lwc='perl path/to/line-word-count.pl'

前述の分割したファイルを収めたディレクトリでツールを実行すると,各テキストファイルの行数,文字数,それらの合計が出力されます注2⁠。

$ lwc
01_beginning.txt => lines: 74 words: 6943
02_Franz-Schubert.txt =>    lines: 130 words: 3989
03_Robert-Schumann.txt =>   lines: 124 words: 5231
04_Frederic-Chopin.txt =>   lines: 110 words: 4741
05_Franz-Liszt.txt =>   lines: 59 words: 1774
06_Richard-Wagner.txt =>    lines: 186 words: 8028
07_Johannes-Brahms.txt =>   lines: 79 words: 1922
08_Gabriel-Faure.txt => lines: 111 words: 3382
09_Gustav-Mahler.txt => lines: 54 words: 1976
10_Richard-Strauss.txt =>   lines: 107 words: 2689
11_Pyotr-Tchaikovsky.txt => lines: 77 words: 3509
12_Jean-Sibelius.txt => lines: 61 words: 2011
13_conclusion.txt =>    lines: 228 words: 9214

Lines total: 1400
Words total: 55409

こうした長丁場の仕事では,進捗の把握がとても重要です。1つのコマンドを実行するだけで十数本の原稿の状況を一望できるこのツールは,作業の大きな助けになりました。

注1)
bashの複数の処理を一つのコマンドで実行できるようにまとめたものです。
注2)
「ロマン派音楽」をテーマにした巻だったので,19世紀のクラシック音楽の作曲家がファイル名に並んでいます。