Perl ワンライナーとその仲間たち


こちらは[Perl Advent Calendar 2018](https://qiita.com/advent-calendar/2018/perl)の18日目の記事になります。昨日は、Morichanさんによる、[クラス図とPerlの対応付け](https://qiita.com/Morichan/items/cfa83fee6d451847ef85) でした。

さて、みなさん、日頃からワンライナーは使ってますでしょうか？
これまで何度となく出てきたネタかとは思いますが、Perlによるワンライナーについて改めて整理してみます。
(…本記事は今年の[YAPC::Okinawa 2018 ONNASON](https://yapcjapan.org/2018okinawa/)の[「Perlを中心としたワンライナーあれこれ」](https://speakerdeck.com/teckl/perlwozhong-xin-tositawanrainaarekore)の加筆・訂正版ですｗ)

# ワンライナーとは
「ワンライナー」とは、たった1行だけのプログラムです。
プログラムを書きたいが、 エディタを起動するほどの手間はかけたくない、というときに威力を発揮します。
日本語で言うところの、いわゆる一行野郎です。
最近界隈で人気の[シェル芸](https://twitter.com/search?q=%23%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8&src=typd)的な分野などでも使えると思います。

---

# 基本編

perlでは、コマンドラインオプションのことを「スイッチ」と言います。
いろいろとあるのですが、よく使うものから抜粋して紹介します。

## `-e <処理>` : 処理の実行

ワンライナーのすべてはここから。
後続の処理をコマンドラインのプログラムとして実行します。

```bash
$ perl -e 'print "Hello World!"'
Hello World!$
$ perl -e 'print 4 * 3'
12$
```

## `-E <処理>` : 処理の実行
`-e` と同様に振る舞いますが、

`use feature ':all';`
や、
`use feature 'current_sub', 'bitwise', 'evalbytes', 'fc', 'postderef_qq', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval'; # perl v5.28.0の場合 `

などと同等の効果があり、特に `print` よりも短くて済み、自動的に末尾に改行を付けてくれる `say` が使用可能になります。

```perl
$ perl -E 'say "Hello World!"' # say が使えるようになるので、末尾の"\n"を省略出来る
Hello World!
$
```

# `-l` : 行末処理

入力行をchomp してくれて、またprint時に改行を追加してくれます。（rubyのputs的）

```perl
# say ではないため、改行コードが含まれない
$ perl -e 'print "Hello World!"'
Hello World!$
# -l しているので、改行してくれる
$ perl -le 'print "Hello World!"'
Hello World!
$
# -E でsayを使ったのとほぼ同じです
$ perl -E 'say "Hello World!"'
Hello World!
$
```

`-le` を使ってprintしても、`-E` で sayを使っても同じですが、ワンライナーではタイプ数が少なく済ませる事が楽なので、 `-E` でsayを使う方が良いかもしれません。
※ Perlのバージョンがまだ `5.8系` という深遠なる事情がある方は `-l` を使ってくださいｗ
※ `-l` には入力レコードセパレータを変更する事も出来るのですが、ここでは割愛します

# `-n` : 暗黙の読み込みループ（出力なし）

入力データの各行を処理します。

```perl
while (<>) {
    処理;
}
```
のイメージです。出力は無いため、明示的にprintをする必要があります。

```perl
$ echo -e "yapc\nramen" | perl -ne 'print '
yapc
ramen
```

# `-p` : 暗黙の読み込みループ（出力あり）

入力データの各行を処理して、printします。

```
while (<>) {
    処理;
} continue {
    print;
}
```
のイメージです。

```perl
# tsvをcsvに置換
$ perl -p -e 's/\t/,/g' /tmp/hoge.tsv > /tmp/hoge.csv
# 単純な文字列の置換の場合はsedの方が楽かも…
$ sed -e "s/\t/,/g" /tmp/hoge.tsv > /tmp/hoge.csv
```

# `-i拡張子  ファイル名` : 上書き編集を有効にする

`-p` スイッチと一緒に使うと、入力したファイルの中身を置換することができます。

```perl
# 対象ディレクトリ内の htmlファイル中の 2018- を 2019- に置換
$ find target_dir  -type f -name '*.html' | \
 xargs perl -pi -e 's/2018-/2019-/g'
# 置換前のファイルを /tmp/hoge.csv.orig というバックアップファイルとして残し、対象ファイルを置換
$ perl -i.orig -pe 's/坦々麺/担々麺/g' /tmp/hoge.csv
```

# `-a` : 自動スプリットモード（awk的）

自動スプリットモードになり、awk っぽい使い心地になります。

`-n` や `-p` と一緒に用いると、自動でsplitモードになり、配列 `@F` に値が代入されます。デフォルトの区切り文字はスペースです。
awkと似ていますが、添字は0から始まるため、注意が必要です。

```perl
$ echo -e "yapc ramen gyouza"
yapc ramen gyouza
$ echo -e "yapc ramen gyouza" | perl -ale 'print $F[0]'   # 配列 `@F` の添字は`0`から
yapc
$ echo -e "yapc ramen gyouza" | perl -ale 'print $F[1]'
ramen
$ echo -e "yapc ramen gyouza" | awk '{print $1}'          # awkのフィールドは `$1` から
yapc
$ echo -e "yapc ramen gyouza" | awk '{print $0}'          # awkの`$0`は現在行すべてになる
yapc ramen gyouza
```

awk 同様に、`-F` を使うと区切り文字を変更できます。

```perl
$ head -n 3 KEN_ALL.CSV | nkf -w
01101,"060  ","0600000","ホッカイドウ","サッポロシチュウオウク","イカニケイサイガナイバアイ","北海道","札幌市中央区","以下に掲載がない場合",0,0,0,0,0,0
01101,"064  ","0640941","ホッカイドウ","サッポロシチュウオウク","アサヒガオカ","北海道","札幌市中央区","旭ケ丘",0,0,1,0,0,0
01101,"060  ","0600041","ホッカイドウ","サッポロシチュウオウク","オオドオリヒガシ","北海道","札幌市中央区","大通東",0,0,1,0,0,0

# 区切り文字を "," に変更することでCSVに対応
$ head -n 3 KEN_ALL.CSV | nkf -w | perl -F, -lane 'print $F[3]'
"ホッカイドウ"
"ホッカイドウ"
"ホッカイドウ"
```

```perl
# /etc/passwd からユーザ名のみを抽出
$ perl -F: -lanE 'say $F[4]' /etc/passwd | tail -5
Docker User
Unbound DNS resolver
Rpcbind Daemon
RPC Service User
Anonymous NFS User
```

# `-Mモジュール名` : 指定されたモジュールをロード

コマンドラインからPerlモジュールを使用することができます。
つまりなんでも出来るので夢が広がります。

```perl
# LWPでHTMLを取得してgrep
$ perl -MLWP::Simple -e 'getprint "http://www.perl.org/"' | grep title
    <title>The Perl Programming Language - www.perl.org</title>

# strftime の %Y と %G で違う挙動をワンライナーで確認
$ perl -MTime::Piece -E \ 
'say Time::Piece->strptime("2014-12-30", "%Y-%m-%d")->strftime("%Y")'
2014
$ perl -MTime::Piece -E \
'say Time::Piece->strptime("2014-12-30", "%Y-%m-%d")->strftime("%G")'
2015
```

# `-C` : Perl Unicode制御

Perl Unicode を制御します。
flagged utf8(Perl内部表現) を、バイト列に変換します。

```perl
$ perl  -E 'say "ラーメン"'  # 普段は意識する必要は無い
ラーメン
$ perl -MEncode  -E 'say decode_utf8("ラーメン")'  # decodeされた文字列は Wide characterの警告が出てしまう
Wide character in say at -e line 1.
ラーメン
$ perl -C -MEncode  -E 'say decode_utf8("ラーメン")'  # -C があるので、内部表現をencodeしてくれる
ラーメン
```

※v5.8.1以前の -C オプションは Win32専用のスイッチだったそうです

# -MO=Deparse : コマンドラインをスクリプト化

[B::Deparseコアモジュール](https://perldoc.perl.org/B/Deparse.html) を使って、ワンライナーだと一見分かりにくいようなコードをコマンドラインではなく、スクリプトだったらどういうコードを実行しているかを確認する事ができます。ワンライナーに慣れるまで超便利です。

```perl
# ワンライナーのコマンドラインをもしスクリプトで書いたらどうなるかを -MO=Deparse で表示
$ head -n 3 KEN_ALL.CSV | nkf -w | perl -MO=Deparse -F, -lane 'print $F[3]'
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = readline ARGV)) {
    chomp $_;
    our @F = split(/,/, $_, 0);
    print $F[3];
}
-e syntax OK
```
[404 Blog Not Found:perl - ワンライナーの書き方入門](http://blog.livedoor.jp/dankogai/archives/51026593.html)

# ワンライナーで役に立つPerlの特殊変数
- `$.`  ： 現在の行番号
- `$,`  ： print引数のセパレータ
- `$/`  ： 入力（open）時の行区切り文字
- `$\`  ： 出力（print）時の行区切り文字
- `$!`  ： エラーの内容

# もっと知りたい人は

perlコマンドラインについてもっと知りたい人は、公式を見られたほうが良いかと思います。

```perl
$ perldoc perlrun
```

もしくは日本語訳もあります
http://perldoc.jp/docs/perl/5.22.1/perlrun.pod

---

# 実践編

## アクセスログ調査

ワンライナーが最も活きてくるのは、サーバ運用時のログの解析だと思います。

### 直近のアクセス元IPの上位を降順に表示

```perl
$ tail -500000  access_log  | perl -lane 'print $F[0]' | sort | \
uniq -c | sort -nr | head -3
  72802 11.22.33.44
    527 222.33.44.55
    521 3.4.5.6
```

`perl -lane 'print $F[0]'`
は、
`awk '{print $1}'`
でも
`cut -f 1 -d ' '`
などでも問題ありません。

### 直近のアクセス元のユーザーエージェント上位を知りたい

```perl
# UserAgent上位を降順にソート
$ tail -500000  access_log  | perl -F'"' -lane 'print $F[5]' | \
sort | uniq -c | sort -nr | head -4
 756981 Mozilla/5.0 (compatible; EvilBot/3.0; +http://www.example.com/evilbot.html)
   7192 Mozilla/5.0 (compatible; Normalbot/2.1; +http://www.example.com/bot.html)
   1277 Mozilla/5.0 (compatible; smallbot/2.0; +http://www.example.com/smallbot.htm)
    253 Mozilla/5.0 (compatible; minbot/2.0; +http://www.example.com/min.htm)
```
たいていの場合、これでrobots.txtを読まないようなGAにも載らない行儀の悪いbotが突然来はじめてるかどうかの傾向が掴めたりします。
見慣れないbotがあるかどうかは、普段から見ていないと分からないところもありますが…

### エラー系の怪しいステータスコードのログを監視したい

デプロイ後はエラー系のログ(正常系以外のもの)だけに注視したい事が多いかと思います。

```perl
# エラー系のログを雑にtail
$ tail -F combined_log | awk '$9 !~ /200|301|302|304/ {print}'

# perlの場合
$ tail -F combined_log | perl -lane 'print if $F[8] !~ /200|301|302|304/'
```

### 分単位にアクセス数を集計したい

```perl
# 分単位のリクエスト数
$ cat access_log  | perl -lne 'm{2018:(\d+):(\d+)} and print "$1:$2"' | \
sort | uniq -c | head
   6559 05:06
   5642 05:07
  89774 05:08
   5592 05:09
   4010 05:10
```

特定の時間帯だけ大量にクロールが来ているかどうかがわかるかと思います。

### IE11の各Windows毎の割合を知りたい
```
# IE11のUA文字列で、Windows NTの後ろの数字を抜き出す
$ head -500000  access_log  | egrep  'rv:11\.0' | \
perl -lane '/Windows NT ([\d.]+)/ && print $1' | sort | uniq -c | sort -nr | head
  11160 6.1    # Windows 7
   8006 10.0   # Windows 10
   5769 6.3    # Windows 8.1
     12 6.2    # Windows 8
      1 5.1    # Windows XP
```
[Understanding user-agent strings (Internet Explorer) | Microsoft Docs](https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537503(v=vs.85))

### 特定のUAが全体に占める比率（ブラウザシェア）を知りたい

`$.` の特殊変数(現在の行数を表す)を使うと楽です

```perl
# IE11の比率
$ cat access_log | perl -lane '/rv:11\.0/ && $cnt++ ; END {print ($cnt / $. ) }  '
0.065
# Firefoxの全体の比率
$ cat access_log | perl -lane '/Firefox/i && $cnt++ ; END {print ($cnt / $. ) }  '
0.0734

# Androidのバージョン毎の比率
$ zcat access_log.20181217.gz  | grep Android | egrep -i -v 'crawler|bot' | perl -lane '/Android ([\d.]+);/ ; $key{$1}++; $cnt++; END {  for (sort { $key{$b} <=> $key{$a} } keys %key) { print sprintf("%s\t%d\t%.4f %", $_, $key{$_},  $key{$_} / $cnt * 100 )  };  } ' | head
8.0.0   522538  46.9889 %
7.0     156429  14.0668 %
6.0.1   98894   8.8930 %
8.1.0   59933   5.3894 %
7.1.1   52959   4.7623 %
9       34892   3.1376 %
5.0.2   34071   3.0638 %
5.1.1   31224   2.8078 %
6.0     28369   2.5511 %
4.4.2   19913   1.7907 %
```

### 生ログのリクエスト平均秒数を調査したい

例えば以下のような末尾に `$request_time` が入っているnginxログがあった場合に、

```bash
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" $request_time';
```

1リクエストあたりの平均秒数を求めるには、

```perl
# awk でのフィールドの最後を表す `$NF` は、Perlだと `$F[-1]` で取れます
$ cat access.log | perl -lane '$sum += $F[-1]; END { print sprintf("avg %s sec (%s rec) ", ($sum / $.) , $.) }'
avg 0.849773958213274 sec (584069 rec)
```

### 生ログのリモートIPからCIDR形式に変換したい

リモートIPから whois 経由でIPのrangeを調べて、[Net::CIDR](https://metacpan.org/pod/Net::CIDR) モジュールを使うとCIDR形式に変換できます。

```perl
$ cat access.log | grep SPAM_UA | awk {'print $1'}  | sort | xargs -n1 whois | grep 'inetnum:' | awk '{print $2, $3, $4}' | perl -MNet::CIDR -lanE  'say Net::CIDR::range2cidr($_)' | sort  | uniq
11.22.136.0/21
11.22.144.0/20
11.22.160.0/22
```

---

# その他雑多なワンライナー

## ちょっとしたCSVの合計（SUM）を集計する

```perl
# こんなCSVがあるとして、各行の金額の合計を求めたい
$ echo -e "ラーメン,690\n味玉,100\n餃子,300"
ラーメン,690
味玉,100
餃子,300
# 金額の列を加算し、 END {} を使って最後に金額の合計値だけ出力
$ echo -e "ラーメン,690\n味玉,100\n餃子,300" | \
 perl -F, -lane '$sum += $F[1]; END {print $sum}'
1090
```

## jpeg/jpgの拡張子を統一させたい

```perl
$ find target_dir -type f -name \*.jpeg | perl -nle '$o=$_;s/\.jpe?g/.jpg/; rename $o,$_'
```

## IPコマンドからアドレスを抽出したい

```
$ ip address list eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 56:bd:e6:e0:66:e3 brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.43/24 brd 172.16.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::54bd:e6ff:fee0:66e0/64 scope link
       valid_lft forever preferred_lft forever
$ ip address list eth0 | perl -MRegexp::Common -lne 'print $1 if /($RE{net}{IPv4})/'
172.16.0.43
$ ip address list eth0 | perl -MRegexp::Common -lne 'print $1 if /($RE{net}{IPv6})/'
fe80::54bd:e6ff:fee0:66e0
```

## パスワードをランダムに生成したい

```perl
$ perl -le 'print map { (a..z)[rand 26] } 1..8'
hrypqbow
```
※ここでは一例として紹介していますが、実際にPerlでやるなら[String::Random](https://metacpan.org/pod/String::Random)モジュール、Linux等の場合だと`pwgen`, `mkpasswd` コマンドを使うなどした方が良さそうです。

## ファイル中の空行を削除したい

```perl

$ perl -i.orig -ne '/^\s*$/ or print' list.txt
```

## IPアドレスを整数に変換したい

```perl
$ perl -le 'print unpack("N", 127.0.0.1)'
2130706433
$ perl -le 'print unpack("N", 127.0.1.1)'
2130706689
# 整数をIPアドレスに戻す
$ perl -MSocket=inet_ntoa -le 'print inet_ntoa(pack("N", 2130706433))'
127.0.0.1
$ perl -MSocket=inet_ntoa -le 'print inet_ntoa(pack("N", 2130706689))'
127.0.1.1
```


## URIエスケープをシェルスクリプトの関数として登録したい

登録しておくと結構便利かもです。

```perl
$ urlescape () { perl -MURI::Escape -lne 'print uri_escape($_)' <<< "$1" }
$ urlunescape () { perl -MURI::Escape -lne 'print uri_unescape($_)' <<< "$1"; }

$ urlescape https://www.perl.org/
https%3A%2F%2Fwww.perl.org%2F
$ urlunescape https%3A%2F%2Fwww.perl.org%2F
https://www.perl.org/
```


## 大量URLからリンク切れやステータスコードを調べたい

```bash
# 大量のURLのテキストから、ステータスコードを雑にチェックする
$ cat /tmp/url.txt | xargs -t -L1 -P1  curl -X GET -I -s  | grep HTTP
curl -X GET -I -s mojolicious.org
HTTP/1.1 200 OK
curl -X GET -I -s mojolicious.io
HTTP/1.1 301 Moved Permanently
curl -X GET -I -s mojocasts.com
HTTP/1.1 302 Found
curl -X GET -I -s http://example.com/not_found.txt
HTTP/1.1 404 Not Found
```

## dockerで `<none>` のイメージを一括削除したい

```bash
$ docker images -a | perl -lane '/<none>/ && print $F[2]' | xargs docker rmi
```
ワンライナーの事例紹介ということで載せていますが、この用途の場合 `docker image prune` を使った方が良さそうですｗ
https://docs.docker.com/engine/reference/commandline/image_prune/

## 素数を数えて落ちつきたい
```perl
$ perl -e 'print "落ちつくんだ…素数を数えて落ちつくんだ… "; \
for(1 .. 100){print "$_…" if $_==2 || 2**($_-1) %$_==1}'
落ちつくんだ…素数を数えて落ちつくんだ… 2…3…5…7…11…13…17…19…23…29…31…37…41…43…47…53…59…61…67…71…73…79…83…89…97…%
```

## calコマンド（カレンダー）を例の NaN カレンダー風に加工したい

```bash
$ cal
    December 2018
Su Mo Tu We Th Fr Sa
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

$ cal | perl -ne ' s/.*/<< < Invalid date > >>/ && print  if $.==1;print if $. ==2 ;  s/..(.|$)/NaN$1/g ; print if $.>2 && $.<9 '
<< < Invalid date > >>
Su Mo Tu We Th Fr Sa
NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN NaN NaN
NaN NaN
```

## MTフォーマットのテキストファイルからコメントの投稿者と日付をそれっぽく抽出したい

```perl
$ cat /tmp/mt.txt | grep -oP  'COMMENT:[\s\S]*?AUTHOR:[\s\S]*?DATE: .*?(AM|PM)' | egrep 'AUTHOR:|DATE:' | perl -0lanE ' s,AUTHOR:(.+)(?:[\s\S]+?)DATE:,$1$2,mg; say $_'   | head
 名無しさん 01/25/2018 06:27:21 PM
 名無しさん 01/25/2018 06:28:07 PM
```

## Unicode絵文字の :bow: の種類をテストしたい

```perl
$ perl -C -E 'for my $s (9794, 9792){ for(0..4) {say "\x{1f647}" . scalar(chr(127995 + $_)) . scalar(chr(8205)) . scalar(chr($s)) } }'
🙇🏻‍♂
🙇🏼‍♂
🙇🏽‍♂
🙇🏾‍♂
🙇🏿‍♂
🙇🏻‍♀
🙇🏼‍♀
🙇🏽‍♀
🙇🏾‍♀
🙇🏿‍♀
```

## 鶏が先か、卵が先か

```perl
$ perl -E ' say sort ("🥚", "🐣", "🍳", "🐔", "🐓", "🐤", "🐥" ) '
🍳🐓🐔🐣🐤🐥🥚
```

# スクレイピング編

Perlでスクレイピングといえば `Web::Scraper` が浮かびますが、ワンライナーでやるにはちょっと厳しかったりします。

そこで、Perlで有名なWebアプリケーションフレームワークの Mojolicious がありますが、そこに含まれているモジュールに [ojo.pm](https://metacpan.org/pod/ojo) というのがあります。
モジュールスイッチの `-M` とセットにすると、`-Mojo` になります。これはカッコいいですね。

## 「阿部寛のホームページ」から要素を取得

```perl
# 阿部寛さんのホームページからtitleタグを取得
$ perl -Mojo -E \
'say g("http://abehiroshi.la.coocan.jp/")->dom->at("title")' | nkf -w
<title>阿部寛のホームページ</title>

# 阿部寛さんのホームページから誕生日を取得
$ perl -Mojo -E 'say g("http://abehiroshi.la.coocan.jp/top.htm")->dom("td")->[4]->text' | nkf -w
生年月日 1964年6月22日
```

## MySQL 5.5 と 5.7 のKeyword(予約語の変更点をざっくりチェックしたい)

```perl
$ perl -MData::Dumper -MText::Diff -Mojo -lE 'my $data; for my $ver(qw(5.5 5.7)) { say $ver; g( sprintf("https://dev.mysql.com/doc/refman/%s/en/keywords.html",$ver))->dom->find("div[class=\"simplesect\"]")->[0]->find("code[class=\"literal\"]")->map(sub{ $data->{$ver}->{$_->text}++ }) };my $str1= join "\n", sort keys %{$data->{5.5}};my $str2 = join "\n", sort keys %{$data->{5.7}}; say diff \$str1, \$str2 '

```

## それ以外の ojo.pm
他にも `ojo.pm` には素敵なワンライナーコマンドたちがあります。

Dumperやjsonで出力したり、ワンライナーでWEBアプリを立ち上げたり、ベンチマークなども出来るようです。

```perl
# Data::Dumperのwrapper `r`
$ perl -Mojo -E 'print r({hello => "world"})'
{
  "hello" => "world"
}

# いつもは-MData::Dumper としなければいけないが
$ perl -MData::Dumper -MTime::Piece -E 'print Dumper(Time::Piece->new)'
$VAR1 = bless( [
                 2,
                 37,
                 2,
                 18,
                 11,
                 '118',
                 2,
                 351,
                 0,
                 1545068222,
                 1
                 ], 'Time::Piece' );

# -Mojo の `r` を使ったほうがタイプ数が少ないので少し楽
$ perl -Mojo -MTime::Piece -E 'print r(Time::Piece->new)'
bless( [
  43,
  35,
  2,
  18,
  11,
  118,
  2,
  351,
  0,
  "1545068143",
  1
], 'Time::Piece' )
```


### Perlのデータ構造をサクッとjsonに

```perl

# 普通はこうだが
$ perl -MJSON -E 'say JSON->new->encode({hello => "world"})'
{"hello":"world"}
# -Mojo の j を使うとタイプ数が減ります
$ perl -Mojo -E 'say j({hello => "world"})'
{"hello":"world"}

# その逆も可能
$ echo '{"hello":"world"}' | perl -Mojo -E 'say j(<>)->{hello}'
world

```

### 簡単なJSONのモックサーバを上げたい

```perl
$ perl -Mojo -E 'get "/" => { json => {hello => "world"} }; get "/yapc" => { json => {yapc => "tokyo 2019"} }; app->start' daemon
Server available at http://127.0.0.1:3000

$ curl localhost:3000
{"hello":"world"}
$ curl localhost:3000/yapc
{"yapc":"tokyo 2019"}
```

組み合わせで、いろいろ出来ます。


```perl
# jq と組み合わせる
$ perl -Mojo -C -E 'say g( "https://spreadsheets.google.com/feeds/list/12QoP57c2ykO9VD_eNygvhkEUNRT8IS65dieeN5XiQqI/on6oryq/public/values?alt=json" )->text' | jq -r '.feed.entry[]."gsx$title"."$t" ' | head
2019年冬のPerl
Perl5の静的解析入門　機械と人間双方の歩み寄りによる平和編
Perlでも分散トレーシングしたい！ - AWS::XRayによる解析とその実装
ログにやさしいDB設計
レガシーPerlビルド 〜現代に蘇るPerl[1..5].0とPerl6〜
```

ojo.pm についてもっと詳しく知りたい方は以下を参照されると良いかと思います。
http://mojolicious.org/perldoc/ojo
https://mojolicious.io/blog/2017/12/23/day-23-one-liners-for-fun-and-profit/

---

さらにワンライナーで攻めたい方や、Unix哲学を学びたい方はこの
 [ミニマルPerl ――Unix/LinuxユーザのためのPerl習得法](https://www.oreilly.co.jp/books/9784873113685/) 
がとても良さそうです。（「ミニマル」と言いつつ、かなり分厚いボリュームなので自分もまだ最後まで読み切れてません。。）
<img alt="IMG_6162_2.JPEG" src="http://teckl.up.seesaa.net/image/IMG_6162_2-thumbnail2.JPEG" width="240" height="320" border="0">

---

いかがだったでしょうか？

Perlワンライナーは、今日からすぐにでも導入可能だと思いますので、
可能なところから導入してみると良いかと思います。
特に日々の運用や、ちょっとした集計などで威力を発揮してくれると思います。
また、Perlは特に後方互換性を保ってくれる言語なので、おそらく10年後も同じように使えるのではないかと思います。

また、ワンライナーとは直接は関係ないですが、 来年2019年1月26日に開催される [YAPC::Tokyo 2019](https://yapcjapan.org/2019tokyo/) がまだチケット発売中みたいですので、興味を持たれた方は是非チェックしてみてください。
これまでほとんどPerlを書いたことが無い方でも、WEB開発に携わっている方であれば楽しめると思います！特に学生さんは無料とのことです！
（自分も[ひと昔前のレガシーPerl的な話](https://yapcjapan.org/2019tokyo/talks.html#/detail/43)をしようかと思っています…😅）

[【YAPC::Tokyo】学生向け! YAPC::Tokyoを楽しむ方法!!](http://blog.yapcjapan.org/entry/2018/12/17/093306)
[YAPC::Tokyo 2019](https://yapcjapan.org/2019tokyo/)


明日は [take_3](https://qiita.com/take_3)さんによる、「[PerlでREPLをもっと使おう](https://qiita.com/take_3/items/9bfbe369b9176bde6e6a)」です！