Bash 循环调用函数转储负数的shell
我编写了一个shell脚本来自动生成内核代码:Bash 循环调用函数转储负数的shell,bash,shell,Bash,Shell,我编写了一个shell脚本来自动生成内核代码: #!/bin/bash # ----------------------------------------------------------- # Description: Register Blocking CSR kernel auto generation. # ----------------------------------------------------------- #set -x KERNEL_SRC=kernel.c
#!/bin/bash
# -----------------------------------------------------------
# Description: Register Blocking CSR kernel auto generation.
# -----------------------------------------------------------
#set -x
KERNEL_SRC=kernel.cpp
file_gen() {
if [ -f ${KERNEL_SRC} ]
then
rm -f ${KERNEL_SRC}
touch ${KERNEL_SRC}
fi
echo "/*">>${KERNEL_SRC}
echo " * Register Blocking CSR implement.">>${KERNEL_SRC}
echo " *">>${KERNEL_SRC}
echo " */">>${KERNEL_SRC}
echo >>${KERNEL_SRC}
echo >>${KERNEL_SRC}
}
emit_func_header() {
R=$1
C=$2
echo "void bcsr_${R}x${C}(const int &bm, const int *b_row_start, const int *b_col_idx," >> ${KERNEL_SRC}
echo "const double *b_values, const double *x, double *y) {" >> ${KERNEL_SRC}
}
emit_func_body() {
local R=${1}
local C=${2}
#echo ${R} ${C}
echo "int i, j;" >>${KERNEL_SRC}
echo "double" >>${KERNEL_SRC}
local m=$(( ${R} - 1 ))
# emit d0, d1, ..., d(r-1), x0, x1, ..., x(c-1)
for i in `seq 0 $m`
do
echo "d${i}, ">>${KERNEL_SRC}
done
local t=$(( ${C} - 1 ))
for i in `seq 0 $t`
do
if [ ${i} -eq ${t} ]
then
echo "x${i};">>${KERNEL_SRC}
else
echo "x${i}, ">>${KERNEL_SRC}
fi
done
# emit outer loop
echo "for (i = 0; i < bm; ++i) {">>${KERNEL_SRC}
# init d0, d1, ..., d(r-1)
for i in `seq 0 $m`
do
echo "d${i} = y[${R} * i + ${i}];">>${KERNEL_SRC}
done
# emit inner loop
echo "for (j = b_row_start[i]; j < b_row_start[i + 1]; ++j, b_values += ${R} * ${C}) {">>${KERNEL_SRC}
# init x0, x1, ..., x(c-1)
for i in `seq 0 $t`
do
echo "x${i} = x[${C} * b_col_idx[j] + ${i}];">>${KERNEL_SRC}
done
# reduce d0, d1, ..., d(r-1)
for i in `seq 0 $t`
do
for j in `seq 0 $m`
do
index=$(( $(( ${j} * ${C} )) + ${i} ))
echo "d${j} += b_values[${index}] * x${i};">>${KERNEL_SRC}
done
done
# write back d0, d1, ..., d(r-1)
for i in `seq 0 $m`
do
echo "y[${R} * i + ${i}] = d${i};">>${KERNEL_SRC}
done
# end inner loop
echo "}">>${KERNEL_SRC}
# end outer loop
echo "}">>${KERNEL_SRC}
}
emit_func_tail() {
echo "}" >> ${KERNEL_SRC}
}
echo "Begin to generate kernel..."
file_gen
for i in `seq 1 12`
do
for j in `seq 1 12`
do
echo ${i} ${j}
emit_func_header ${i} ${j}
emit_func_body ${i} ${j}
emit_func_tail
echo >>${KERNEL_SRC}
done
done
#clang-format -i $KERNEL_SRC
echo "End kernel generating..."
总共144个bcsr子例程,但实际输出包含负数,例如:
bcsr_ - 1x3(...)
由于核心代码是:
for i in `seq 1 12`
do
for j in `seq 1 12`
do
echo ${i} ${j}
emit_func_header ${i} ${j}
emit_func_body ${i} ${j}
emit_func_tail
echo >>${KERNEL_SRC}
done
done
外部循环的范围为1到12,内部循环的范围为1到12,其预期输出不应包含任何负数
Bash版本:
GNU bash,版本3.2.571-发布x86_64-apple-darwin17
版权所有C 2007自由软件基金会, < P>这可能是一个范围问题,内环称为函数EmithFielySype包含本地变量i,当我用另一个名称改变循环索引时, 一切正常:
for _i in `seq 1 12`
do
for _j in `seq 1 12`
do
echo ${_i} ${_j}
emit_func_header ${_i} ${_j}
emit_func_body ${_i} ${_j}
emit_func_tail
echo >>${KERNEL_SRC}
done
done
其中一个函数使用全局变量i并覆盖主循环中的值
# Correspondingly refactor file_gen; no need to rm or touch
file_gen >"$KERNEL_SRC"
for i in `seq 1 12`
do
for j in `seq 1 12`
do
echo "$i $j" >&2
emit_func_header "$i" "$j"
emit_func_body "$i" "$j"
emit_func_tail
echo
done
done >>"$KERNEL_SRC"
快速修复方法是将局部i添加到任何希望将其用作局部变量的函数中,并通常检查所有函数,以确保它们使用的所有变量都声明为局部变量
如果您不决定将其完全重写为具有更好范围规则的语言,我还建议您为所有变量添加适当的引号,并检查shell脚本的重定向规则。特别是,将任何诊断消息打印到标准错误,并在主循环中使用单个重定向
# Correspondingly refactor file_gen; no need to rm or touch
file_gen >"$KERNEL_SRC"
for i in `seq 1 12`
do
for j in `seq 1 12`
do
echo "$i $j" >&2
emit_func_header "$i" "$j"
emit_func_body "$i" "$j"
emit_func_tail
echo
done
done >>"$KERNEL_SRC"
只要你使用BASH,你可能还想用传统的三参数for循环替换SEQ。< /P>这不会解决你的问题,但是你应该考虑引用变量。写${i}或者只写$i而不是${i}。这是非常痛苦的,你能总结一下它应该做什么以及为什么结果是错误的吗?另外,切题来说,正确的输出应该是我想在Awk.OT中重写:我可以推荐吗?我使用Ubuntu 18.04上的bash 4.4.19复制并执行了您的脚本。没有bcsr_u1x3。对我来说,bcsr_uu后面总是跟一个数字。我无法重现你的问题。