我有一个小的bash脚本,其中包含一个case语句,如果第一个参数与case参数匹配,它会回显随机数据。 代码如下:
#!/usr/bin/env bash '
AC='auto-increment'
UUID='uuid'
LAT='lat'
LONG='long'
IP='ip'
generate_mock_data() {
# ARGS: $1 - data type, $2 - loop index
case ${1} in
${AC})
echo ${2} ;;
${UUID})
uuidgen ;;
${LAT})
echo $((RANDOM % 180 - 90)).$(shuf -i1000000-9999999 -n1) ;;
${LONG})
echo $((RANDOM % 360 - 180)).$(shuf -i1000000-9999999 -n1) ;;
${IP})
echo $((RANDOM%256)).$((RANDOM%256)).$((RANDOM%256)).$((RANDOM%256)) ;;
esac
}
# Writing data to file
headers=('auto-increment' 'uuid' 'lat' 'long' 'ip')
for i in {1..2500}; do
for header in "${headers[@]}"; do
echo -n $(generate_mock_data ${header} ${i}),
done
echo # New line
done >> file.csv
但是,只有2500行的执行时间非常慢:
real 0m8.876s
user 0m0.576s
sys 0m0.868s
我究竟做错了什么 ?我有什么办法可以加快这个过程吗?或者bash不是这类操作的正确语言?
我也尝试分析整个脚本,但在查看日志后我没有注意到任何明显的瓶颈。
答案 0 :(得分:4)
看起来你可以用Python快速生成一个UUID,所以如果你只执行一次Python来生成2,500个UUID,并且你不是Python程序员 - 就像我一样;-)那么你可以使用{{{ 1}}:
awk
我的iMac需要0.06秒。
python -c 'import uuid; print("\n".join([str(uuid.uuid4()).upper() for x in range(2500)]))' |
awk '{
lat=-90+180*rand();
lon=-180+360*rand();
ip=int(256*rand()) "." int(256*rand()) "." int(256*rand()) "." int(256*rand());
print NR,$0,lat,lon,ip
}' OFS=,
是“输出字段分隔符” OFS
是行号您可以单独试用Python,如下所示:
NR
答案 1 :(得分:3)
不是真的,但如果你避免不良做法,你可以快速做出相对的事情。
使用ksh93,下面可靠地以0.5-0.6秒的挂钟运行;用bash,1.2-1.3s。
#!/usr/bin/env bash
# Comment these two lines if running with ksh93, obviously. :)
[ -z "$BASH_VERSION" ] && { echo "This requires bash 4.1 or newer" >&2; exit 1; }
[[ $BASH_VERSION = [123].* ]] && { echo "This requires bash 4.1 or newer" >&2; exit 1; }
uuid_stream() {
python -c '
import uuid
try:
while True:
print str(uuid.uuid4()).upper()
except IOError:
pass # probably an EPIPE because we were closed.
'
}
# generate a file descriptor that emits a shuffled stream of integers
exec {large_int_fd}< <(while shuf -r -i1000000-9999999; do :; done)
# generate a file descriptor that emits an endless stream of UUIDs
exec {uuid_fd}< <(uuid_stream)
generate_mock_data() {
typeset val
case $1 in
auto-increment) val="$2" ;;
uuid) IFS= read -r val <&"$uuid_fd" || exit;;
lat) IFS= read -r val <&"$large_int_fd" || exit
val="$((RANDOM % 180 - 90)).$val" ;;
long) IFS= read -r val <&"$large_int_fd" || exit
val="$((RANDOM % 360 - 180)).$val" ;;
ip) val="$((RANDOM%256)).$((RANDOM%256)).$((RANDOM%256)).$((RANDOM%256))" ;;
esac
printf '%s' "$val"
}
for ((i=0; i<2500; i++)); do
for header in auto-increment uuid lat long ip; do
generate_mock_data "$header" "$i"
printf ,
done
echo
done > file.csv
$()
或任何同义词。其中每一项都涉及fork()
- 创建一个新的操作系统级别的流程副本 - 以及一个wait()
,带有一堆FIFO魔法来捕获我们的输出。