シェルのワンライナーでランダムにナンバープレートを生成


大したことはやっていないので初心者向けです。
今回はシェルを用いてワンライナーでナンバープレートを生成します。

先に実行結果を示すと以下のようになります。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 4 | sed -e 's/^0*\(.\+\)$/***\1/' -e 's/^.*\(..\)\(..\)$/\1-\2/' -e 's/^\(\*.\)-/\1 /' | head -n 20
18-84
31-57
23-32
33-08
66-71
80-58
26-13
48-03
37-71
** *9
50-94
62-15
31-94
21-49
18-76
91-93
53-70
79-04
44-32
*3 04

さて、あなたの愛車の番号は見つかったでしょうか。

Step 1. ランダムな番号を生成

Linuxでランダムなデータを得るためには、/dev/urandomを表示すればよいです。

$ cat /dev/urandom                                                                             
ȇoG�c/~1}&�}CwÀݖ$abu֭}I^tO�U�&hwKe�v�$�iB�3Ɠr&n��G�\�}��7Jj�)8$hEw5
                                                                   &A�}f?�7,.��kPYt��{%+��6���[1k2eUc8kL݅\w!��������w9z����p9ɣr?Șt(�Iw�f(ʊt�n�nnt'�L%b|*T8sL��;�vЎ7edqf3���(�h
ŗD�cC+QeA�4qz4Nq,t2Æ>Y eR|�WF9q�0�Zaױ'9X%lqmy�[@�uH:�
p^B   zK�       g}jW�=�ݯh,e��ЊW...(以下略)

出力が無限に続く場合は、Ctrl+Cを押して終了してください。
見ての通り、文字化けしてしまって読めません。そこで、trを使用してこのランダムなバイト列をランダムな数字列に変換してあげます。

$ cat /dev/urandom | tr -dc '0-9'                                                      
091783834888843510941299184940373171052314853431411596244506282697043452700603714627453442077114...(以下略)

これで数字列を取り出せました。これをナンバープレートの4桁に合わせて改行してあげます。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 4                                             
0408
7829
6660
3060
6273
7102
4233
2553
6386
0114
...(以下略)

このままでは出力が無限に続いてしまうため、headを使用して先頭の数行のみを取り出してみます。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 4 | head                                             
0408
7829
6660
3060
6273
7102
4233
2553
6386
0114

これで4桁の数字列が得られましたね。

Step 2. 先頭の0*にする

実際のナンバープレートは、数字列の先頭が0で始まる場合は、0の代わりに点を表示します。(ここでは点はascii文字としては表示しにくいため*で代用します。)
また、先頭の0の次にさらに0が続く場合は、それも*に置換する必要があります。

これらの操作を実行するため、ここでは

  • 数字列の先頭が0で始まる場合、先頭から連続する0***に置き換える(最後の0は残す)
  • 全体の文字数が4文字になるよう、先頭の余分な文字を削除する。

という順番で処理をしています。まず1つめから。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 4 | sed -e 's/^0*\(.\+\)$/***\1/'  | head
***1423
***4924
***1503
***285
***9069
***2054
***9453
***7307
***1417

そして4文字を残し先頭の余った文字を消します。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 4 | sed -e 's/^0*\(.\+\)$/***\1/' -e 's/^.*\(....\)$/\1/' | head
1912
6348
2718
4158
7943
*216
5893
9387
6403
8581

Step 3. 数字の間に-を入れる

ナンバープレートでは4桁の数字の間にハイフンが入っています。
よって、sedを使ってこの区切り文字を入れてみましょう。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 4 | sed -e 's/^0*\(.\+\)$/***\1/' -e 's/^.*\(..\)\(..\)$/\1-\2/' | head
56-26
27-64
64-65
36-88
*8-70
47-27
84-16
29-00
47-98
45-81

Step 4. 先頭が*で始まる場合は-を消す

Step 3. までですでに完成したかに見えますが、実はあと1ステップ残っています。
というのも、(先頭の0を数えず)実際の桁数が3桁以下の場合は、-を表示しないのです。

よって、それを加えたコードを以下に示します。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 4 | sed -e 's/^0*\(.\+\)$/***\1/' -e 's/^.*\(..\)\(..\)$/\1-\2/' -e 's/^\(\*.\)-/\1 /' | head
89-45
*8 30
80-26
79-31
89-53
*7 96
50-65
70-57
95-70
46-24

これで冒頭のコードが完成しました。

おまけ: 連番を使う場合

ランダムなナンバープレートではなく、連番を使いたいという場合はseqを使うことができます。

$ seq 0 9999 | sed -e 's/^0*\(.\+\)$/***\1/' -e 's/^.*\(..\)\(..\)$/\1-\2/' -e 's/^\(\*.\)-/\1 /' |less 
** *0
** *1
** *2
** *3
** *4
** *5
** *6
** *7
** *8
** *9
** 10
** 11
** 12
** 13
** 14
** 15
** 16
** 17
** 18
** 19
** 20
...(以下略)