2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ワンライナー自慢大会Advent Calendar 2018

Day 15

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

Last updated at Posted at 2018-12-14

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

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

$ 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
...(以下略)
2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?