Bash 如何在几秒钟内创建大型CSV?
我正在尝试快速创建1000个大型CSV。此函数生成CSV:Bash 如何在几秒钟内创建大型CSV?,bash,csv,Bash,Csv,我正在尝试快速创建1000个大型CSV。此函数生成CSV: function csvGenerator () { for ((i=1; i<=$NUMCSVS; i++)); do CSVNAME=$DIRNAME"-"$CSVPREFIX$i$CSVEXT HEADERARRAY=() if [[ ! -e $CSVNAME ]]; then #Only create csv file if it not exist touch $CSVNAM
function csvGenerator () {
for ((i=1; i<=$NUMCSVS; i++)); do
CSVNAME=$DIRNAME"-"$CSVPREFIX$i$CSVEXT
HEADERARRAY=()
if [[ ! -e $CSVNAME ]]; then #Only create csv file if it not exist
touch $CSVNAME
echo "file: "$CSVNAME "created at $(date)" >> ../status.txt
fi
for ((j=1; j<=$NUMCOLS; j++)); do
if (( j < $NUMCOLS )) ; then
HEADERNAME=$DIRNAME"-csv-"$i"-header-"$j", "
elif (( j == $NUMCOLS )) ; then
HEADERNAME=$DIRNAME"-csv-"$i"-header-"$j
fi
HEADERARRAY+=$HEADERNAME
done
echo $HEADERARRAY > $CSVNAME
for ((k=1; k<=$NUMROWS; k++)); do
ROWARRAY=()
for ((l=1; l<=$NUMCOLS; l++)); do
if (( l < $NUMCOLS )) ; then
ROWVALUE=$DIRNAME"-csv-"$i"-r"$k"c"$l", "
elif (( l == $NUMCOLS )) ; then
ROWVALUE=$DIRNAME"-csv-"$i"-r"$k"c"$l
fi
ROWARRAY+=$ROWVALUE
done
echo $ROWARRAY >> $CSVNAME
done
done
}
该脚本需要约3分钟才能生成一个包含100k行和70列的CSV。我需要做什么才能以1csv/~10秒的速度生成这些CSV?将两个内部for循环重构为这样的循环将节省时间:
for ((j=1; j<$NUMCOLS; ++j)); do
HEADERARRAY+=$DIRNAME"-csv-"$i"-header-"$j", "
done
HEADERARRAY+=$DIRNAME"-csv-"$i"-header-"$NUMCOLS
将两个内部for循环重构为这样的循环将节省时间:
for ((j=1; j<$NUMCOLS; ++j)); do
HEADERARRAY+=$DIRNAME"-csv-"$i"-header-"$j", "
done
HEADERARRAY+=$DIRNAME"-csv-"$i"-header-"$NUMCOLS
让我首先说,bash和performant通常不会在同一句话中同时出现。正如其他评论员所建议的,awk可能是一个很好的选择,在某些意义上是相邻的 我还没有机会运行您的代码,但它每行打开和关闭输出文件一次——在本例中,是100000次。每次它都必须搜索到文件的末尾,以便可以追加最新的行
尝试在j=1的情况下拉取实际的生成;首先,让我说bash和performant通常不会在同一句话中同时出现。正如其他评论员所建议的,awk可能是一个很好的选择,在某些意义上是相邻的 我还没有机会运行您的代码,但它每行打开和关闭输出文件一次——在本例中,是100000次。每次它都必须搜索到文件的末尾,以便可以追加最新的行
尝试在j=1的情况下拉取实际的生成;我想答案不是这样的 这里有一些问题 您没有将数组用作数组。如果将它们视为字符串,则只会影响数组中的第一个元素,这会产生误导。 您使用>>的方式会导致每行打开和关闭一次输出文件。这可能是浪费。 你没有引用你的变量。事实上,你引用的是那些不需要引用的东西,而不是引用那些需要引用的东西。 由于存在与系统变量冲突的风险,不建议使用大写变量名。 Bash不擅长这个。真正地 清理后的函数版本可能如下所示:
csvGenerator2() {
for (( i=1; i<=NUMCSVS; i++ )); do
CSVNAME="$DIRNAME-$CSVPREFIX$i$CSVEXT"
# Only create csv file if it not exist
[[ -e "$CSVNAME" ]] && continue
touch "$CSVNAME"
date "+[%F %T] created: $CSVNAME" | tee -a status.txt >&2
HEADER=""
for (( j=1; j<=NUMCOLS; j++ )); do
printf -v HEADER '%s, %s-csv-%s-header-%s' "$HEADER" "$DIRNAME" "$i" "$j"
done
echo "${HEADER#, }" > "$CSVNAME"
for (( k=1; k<=NUMROWS; k++ )); do
ROW=""
for (( l=1; l<=NUMCOLS; l++ )); do
printf -v ROW '%s, %s-csv-%s-r%sc%s' "$ROW" "$DIRNAME" "$i" "$k" "$l"
done
echo "${ROW#, }"
done >> "$CSVNAME"
done
}
请注意,即使是我的优化bash版本也只比您的原始代码快一点。我认为答案不是这样 这里有一些问题 您没有将数组用作数组。如果将它们视为字符串,则只会影响数组中的第一个元素,这会产生误导。 您使用>>的方式会导致每行打开和关闭一次输出文件。这可能是浪费。 你没有引用你的变量。事实上,你引用的是那些不需要引用的东西,而不是引用那些需要引用的东西。 由于存在与系统变量冲突的风险,不建议使用大写变量名。 Bash不擅长这个。真正地 清理后的函数版本可能如下所示:
csvGenerator2() {
for (( i=1; i<=NUMCSVS; i++ )); do
CSVNAME="$DIRNAME-$CSVPREFIX$i$CSVEXT"
# Only create csv file if it not exist
[[ -e "$CSVNAME" ]] && continue
touch "$CSVNAME"
date "+[%F %T] created: $CSVNAME" | tee -a status.txt >&2
HEADER=""
for (( j=1; j<=NUMCOLS; j++ )); do
printf -v HEADER '%s, %s-csv-%s-header-%s' "$HEADER" "$DIRNAME" "$i" "$j"
done
echo "${HEADER#, }" > "$CSVNAME"
for (( k=1; k<=NUMROWS; k++ )); do
ROW=""
for (( l=1; l<=NUMCOLS; l++ )); do
printf -v ROW '%s, %s-csv-%s-r%sc%s' "$ROW" "$DIRNAME" "$i" "$k" "$l"
done
echo "${ROW#, }"
done >> "$CSVNAME"
done
}
请注意,即使是我优化的bash版本也只比您的原始代码快一点。使用多线程来加速您的任务。您能给我一些关于如何进行的指导吗?所有代码都在一个文件中。我查看了一些示例,但不确定它们是否适用于我的情况。如果您想要速度,请不要使用bash。这就是真正的编程语言的用途。C,C++,java,python,Ruby,JavaScript…选择你的毒药:-正是斯蒂芬C说的。这是做这项工作的错误工具。即使是awk也是一个更好的选择。Awk实际上可能是一个很好的选择。使用多线程加速你的任务你能给我一些关于如何进行的指导吗?所有代码都在一个文件中。我查看了一些示例,但不确定它们是否适用于我的情况。如果您想要速度,请不要使用bash。这就是真正的编程语言的用途。C,C++,java,python,Ruby,JavaScript…选择你的毒药:-正是斯蒂芬C说的。这是做这项工作的错误工具。即使是awk也是一个更好的选择。Awk实际上可能是一个很好的选择。
$ time bash -c '. file; NUMCSVS=1 NUMCOLS=10 NUMROWS=100000 DIRNAME=2 CSVPREFIX=x CSVEXT=.csv csvGenerator2'
[2019-03-29 23:57:26] created: 2-x1.csv
real 0m30.260s
user 0m28.012s
sys 0m1.395s
$ time bash -c '. file; NUMCSVS=1 NUMCOLS=10 NUMROWS=100000 DIRNAME=3 CSVPREFIX=x CSVEXT=.csv csvGenerator3'
[2019-03-29 23:58:23] created: 3-x1.csv
real 0m4.994s
user 0m3.297s
sys 0m1.639s