[シェルスクリプト]ランダムな数値では乱数の生成をしたけど、改めてシェルを使ってのテストデータ生成を考えてみよう。
できるだけ、デフォルトでありそうなコマンドかつ移植性のありそうな方法で。
seqは内部的に浮動小数点数を使っているので、大きな数を指定すると表示が指数表記になる場合がある。
大きな桁数で整数表記のデータが必要であれば、bcを使うのがいいかもしれない。
※のようにGNU dateとBSD dateではオプションが違うので、注意しよう。
Linux版
Mac,BSD版
[シェルスクリプト]ランダムな数値ではodコマンドのオプションを使ってバイナリデータを数値に変換していたけど、文字列とかへの応用も考えるとtrで該当の文字が出現した場合のみ、拾うようにもできる。
桁数はfoldで指定する。
先頭を0埋めしたくなければ、sedで先頭の0を除去しよう。
Linux版
Mac,BSD版
2017/06/18時点でのUnix時間の桁数は10桁だけど、そのままではかなり未来の日付まで登場してしまうので、awkで適当に切ってしまおう。
ただし、awkの乱数種は現在時刻から生成されるので、何度も生成する場合はsrand関数にbashの$RANDOMを渡すなりの工夫が必要となる。
pasteでつなげる方法としては
Linux版
Mac,BSD版
CSV形式で保存したければ、pasteの-dオプションでカンマを指定すればいい。
Linux版
Mac,BSD版
できるだけ、デフォルトでありそうなコマンドかつ移植性のありそうな方法で。
同じ文字列の繰り返し
同じデータを繰り返し生成する場合はyesコマンドに文字列を渡して、headで行数を指定しよう。$ yes ABCDE | head -n5 ABCDE ABCDE ABCDE ABCDE ABCDE
連続する数値を生成
1〜100のような連続データは単純にseqで生成する。0埋めしたい場合は-wオプションやprintfを使えばいい。$ seq 3 1 2 3 $ seq -w 10 01 02 (中略) 09 10 $ seq 3 | xargs printf '%05d\n' 00001 00002 00003
seqは内部的に浮動小数点数を使っているので、大きな数を指定すると表示が指数表記になる場合がある。
$ seq 999998 1000000 999998 999999 1e+06
大きな桁数で整数表記のデータが必要であれば、bcを使うのがいいかもしれない。
$ echo 'for(i=1;i<=1000000;i++)i' | bc -q 1 2 (中略) 999999 1000000
連続する日付を生成
連続の数値データが得られれば、それをUnix時間とみなして、連続日付データも生成できる。※のようにGNU dateとBSD dateではオプションが違うので、注意しよう。
Linux版
$ date -d'20170618' '+%s' 1497711600 $ echo 'i=1497711600;while(n++ < 5){i;i+=86400}' | bc -q | sed -e 's/^/@/' | date -f- '+%Y-%m-%d %T' 2017-06-18 00:00:00 2017-06-19 00:00:00 2017-06-20 00:00:00 2017-06-21 00:00:00 2017-06-22 00:00:00
Mac,BSD版
$ date -j -f '%Y%m%d%H%M%S' '20170618000000' '+%s' 1497711600 $ echo 'i=1497711600;while(n++ < 5){i;i+=86400}' | bc -q | xargs -I{} date -j -r{} '+%Y-%m-%d %T' 2017-06-18 00:00:00 2017-06-19 00:00:00 2017-06-20 00:00:00 2017-06-21 00:00:00 2017-06-22 00:00:00
ランダムな整数を生成
今度はランダムなデータを生成してみよう。[シェルスクリプト]ランダムな数値ではodコマンドのオプションを使ってバイナリデータを数値に変換していたけど、文字列とかへの応用も考えるとtrで該当の文字が出現した場合のみ、拾うようにもできる。
桁数はfoldで指定する。
$ LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w8 | head -n5 29573283 41462132 28552390 09252685 49857674
先頭を0埋めしたくなければ、sedで先頭の0を除去しよう。
$ LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w8 | head -n5 | sed -e 's/^0*//' 29366227 63890313 20093604 2453784 13832814
ランダムな文字列を生成
同じように0-9以外の拾いたい文字をtrで指定すれば、ランダムな文字列も生成できる。$ LC_CTYPE=C tr -dc 'A-Za-z0-9' </dev/urandom | fold -w8 | head -n5 oZJ1Q3Ix E8qvDy33 WuQHDMnt MDfo3pNt FLMmjCfh
ランダムな日付を生成
連続日付データと同様にランダムな日付データも生成してみよう。Linux版
$ date -d'20170618' '+%s' 1497711600 $ LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w10 | sed -e 's/^0*//' | awk '$1<1497711600{ print $1 }' | head -n5 | sed -e 's/^/@/' | date -f- '+%Y-%m-%d %T' 1975-07-09 21:13:43 2001-12-22 01:47:22 2007-05-18 21:53:30 1984-07-13 18:06:16 1995-02-25 23:12:42
Mac,BSD版
$ date -j -f '%Y%m%d%H%M%S' '20170618000000' '+%s' 1497711600 $ LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w10 | sed -e 's/^0*//' | awk '$1<1497711600{ print $1 }' | head -n5 | xargs -I{} date -j -r{} '+%Y-%m-%d %T' 1995-04-28 11:31:12 2008-07-07 20:33:57 1993-07-23 15:54:51 1999-05-09 19:52:59 2006-08-16 21:52:21
2017/06/18時点でのUnix時間の桁数は10桁だけど、そのままではかなり未来の日付まで登場してしまうので、awkで適当に切ってしまおう。
ランダムな浮動小数点数を生成
0〜1の浮動小数点数の乱数を生成したい場合はawkを使おう。ただし、awkの乱数種は現在時刻から生成されるので、何度も生成する場合はsrand関数にbashの$RANDOMを渡すなりの工夫が必要となる。
$ seq 5 | awk "BEGIN{ srand($RANDOM) } { print rand() }" 0.101913 0.67829 0.169584 0.236928 0.35855
テストデータの組を生成
これらの結果をpasteコマンドでつなげば、テストデータの組を生成できる。pasteでつなげる方法としては
- 一時ファイルを使う
- 名前付きパイプを使う
- プロセス置換を使う
Linux版
$ paste <(seq 5) \ <(LC_CTYPE=C tr -dc 'A-Za-z0-9' </dev/urandom | fold -w8 | head -n5) \ <(LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w10 | sed -e 's/^0*//' | awk '$1<1497711600{ print $1 }' | head -n5 | sed -e 's/^/@/' | date -f- '+%Y-%m-%d') 1 CPyGlAdN 2017-02-12 2 0ELSHuu4 2010-03-31 3 h6NxN6WJ 1988-11-15 4 WQ6y52Gp 2005-07-05 5 sURAKOI6 1997-12-12
Mac,BSD版
$ paste <(seq 5) \ <(LC_CTYPE=C tr -dc 'A-Za-z0-9' </dev/urandom | fold -w8 | head -n5) \ <(LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w10 | sed -e 's/^0*//' | awk '$1<1497711600{ print $1 }' | head -n5 | xargs -I{} date -j -r{} '+%Y-%m-%d') 1 e1QPEVO0 2015-05-23 2 wZOdHS5o 2017-01-29 3 GPJkOIHU 1982-09-02 4 nzPg2jvz 1992-03-22 5 BZqtBtkQ 2006-11-20
CSV形式で保存したければ、pasteの-dオプションでカンマを指定すればいい。
Linux版
$ paste -d, <(seq 5) \ <(LC_CTYPE=C tr -dc 'A-Za-z0-9' </dev/urandom | fold -w8 | head -n5) \ <(LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w10 | sed -e 's/^0*//' | awk '$1<1497711600{ print $1 }' | head -n5 | sed -e 's/^/@/' | date -f- '+%Y-%m-%d') 1,k3Pwocom,1996-06-16 2,j4h53ZNY,1994-10-30 3,orMT66yb,1995-08-23 4,xYQ5SVB4,2016-01-25 5,c5IF2oVe,2017-04-22
Mac,BSD版
$ paste -d, <(seq 5) \ <(LC_CTYPE=C tr -dc 'A-Za-z0-9' </dev/urandom | fold -w8 | head -n5) \ <(LC_CTYPE=C tr -dc '0-9' </dev/urandom | fold -w10 | sed -e 's/^0*//' | awk '$1<1497711600{ print $1 }' | head -n5 | xargs -I{} date -j -r{} '+%Y-%m-%d') 1,zk6PpLgI,2002-11-06 2,5gN8q9H9,1996-05-23 3,FtJ3fLpk,1981-05-02 4,G5jfaiDm,1987-08-11 5,lTODWiuB,2016-04-25
0 件のコメント:
コメントを投稿