Performance

改進模擬數據生成

  • August 28, 2017

我正在嘗試使用模擬數據生成 csv

for i in {1..1000000..1}
do 
 echo "$i,$(date -d "2017-08-01 + $(shuf -i 1-31 -n 1) days" +'%Y-%m-%d')" >> $F
done;

從 1 到百萬循環並生成唯一 ID 和隨機日期

但是它的工作速度很慢,是否有任何一條線可以使其平行?

看到最後的結果。

for i in {1..1000000..1}
do 
 echo "$i,$(date -d "2017-08-01 + $(shuf -i 1-31 -n 1) days" +'%Y-%m-%d')" >> $F
done;

Shell 循環很慢,主要有兩個原因使這個特定的循環特別慢:

  1. 在每次迭代中打開並附加到文件。
  2. 在每次迭代中執行兩次外部實用程序 (shuf和)。date很可能內置在echo外殼中,因此產生的成本更少。

輸出重定向最容易補救:

for i in {1..1000000..1}
do 
 echo "$i,$(date -d "2017-08-01 + $(shuf -i 1-31 -n 1) days" +'%Y-%m-%d')" 
done >"$F"

這只會打開一次輸出文件並在循環期間保持打開狀態。


其餘程式碼可以使用awkGNU更有效地完成date(因為您使用的是shuf我假設您在 Linux 系統上,這意味著它很可能date實際上是 GNU date)。

awk 'END { for (i=0;i<100;++i) { printf("2017-08-01 + %d days\n", 1+int(31*rand())) }}' /dev/null

這個東西生成100行

2017-08-01 + 22 days
2017-08-01 + 31 days
2017-08-01 + 11 days
2017-08-01 + 27 days
2017-08-01 + 27 days
2017-08-01 + 20 days
(etc.)

讓我們將這些輸入 GNU date。GNUdate有這個標誌 ,-f讓我們可以批量輸入多個日期規範,例如我們的awk程序輸出的那些:

awk 'END { for (i=0;i<100;++i) { printf("2017-08-01 + %d days\n", 1+int(31*rand())) }}' /dev/null |
date -f - +'%Y-%m-%d'

現在我們得到

2017-08-23
2017-08-27
2017-08-21
2017-08-29
2017-08-25
2017-08-17
2017-08-07
(etc.)

然後只需將唯一 ID(順序整數)添加到每一行:

awk 'END { for (i=0;i<100;++i) { printf("2017-08-01 + %d days\n", 1+int(31*rand())) }}' /dev/null |
date -f - +'%Y-%m-%d' |
awk -vOFS=',' '{ print NR, $0 }'

這給你

1,2017-08-06
2,2017-08-17
3,2017-08-25
4,2017-08-28
5,2017-08-14
6,2017-08-15
7,2017-08-17
8,2017-08-10
9,2017-08-16
10,2017-08-08
(etc.)

現在我們完成了。在這個過程中,我完全忘記了我們有一個 shell 循環。事實證明它是不需要的。

只需將其調高100到您想要的任何值,然後調整隨機數生成器以滿足您的需要。 rand()返回一個浮點值,使得 0 <= number < 1。


顯然,如果您只想在 8 月(一個月有 31 天)的隨機日期,您可以date完全繞過:

awk 'END { for (i=1;i&lt;=100;++i) { printf("%d,2017-08-%02d\n", i, 1+int(31*rand())) }}' /dev/null

使用 GNUawk和 Mike’s awk( mawk),但不使用 BSD awk,您甚至可以直接在以下位置進行正確的日期處理awk

awk 'END { for (i=1;i&lt;=100;++i) { printf("%d,%s\n", i, strftime("%Y-%m-%d", 1501545600 + int(2678400*rand()),1 )) }}' /dev/null

現在我們處理的是 Unix 時間戳而不是天數。1501545600 對應於“Tue Aug 1 00:00:00 UTC 2017”,31 天有 2678400 秒。

引用自:https://unix.stackexchange.com/questions/388655