Performance
改進模擬數據生成
我正在嘗試使用模擬數據生成 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 循環很慢,主要有兩個原因使這個特定的循環特別慢:
- 在每次迭代中打開並附加到文件。
- 在每次迭代中執行兩次外部實用程序 (
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"
這只會打開一次輸出文件並在循環期間保持打開狀態。
其餘程式碼可以使用
awk
GNU更有效地完成date
(因為您使用的是shuf
我假設您在 Linux 系統上,這意味著它很可能date
實際上是 GNUdate
)。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<=100;++i) { printf("%d,2017-08-%02d\n", i, 1+int(31*rand())) }}' /dev/null
使用 GNU
awk
和 Mike’sawk
(mawk
),但不使用 BSDawk
,您甚至可以直接在以下位置進行正確的日期處理awk
:awk 'END { for (i=1;i<=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 秒。