这个脚本不完整,因为我想稍后进行错误测试,但想法是ARG是一个脚本而ARG2是一个目录,而ARG应该标记ARG2中的所有文件。我怎么能这样做,以至于bash知道第一个参数必须是一个脚本而参数2是一个目录?
ARG=$1
ARG2=$2
CHECK=0
aCount=0
bCount=0
cCount=0
dCount=0
fCount=0
if [ $CHECK -e 0 ]; then
for files in $ARG2; do
if [ sh $1 $2 -eq A]; then
aCount=$((aCount+1))
elif [ sh $1 $2 -eq B];
bCount=$((bCount+1))
elif [ sh $1 $2 -eq C];
cCount=$((cCount+1))
elif [ sh $1 $2 -eq D ];
dCount=$((dCount+1))
else;
fCount=$((fCount+1))
fi
done
fi
echo A: $aCount
echo B: $bCount
echo C: $cCount
echo D: $dCount
echo F: $fCount
答案 0 :(得分:4)
通过 shellcheck.net 运行脚本可能会遇到各种错误。
<强>更正:强>
要遍历目录中的文件,请写for file in dir/*
而不是for file in dir
。后者只是循环一次,$file
设置为字符串"dir"
,而不是遍历目录dir/
的内容。
[ sh $1 $2 -eq A]
是一堆混乱的shell结构。您想要捕获脚本的输出,因此需要$(...)
。您正在进行字符串检查,因此您应该使用==
而不是-eq
。纠正两个收益率:
[ $(sh $1 $2) == A ]
我猜$2
应该是$files
。循环变量,是吗?
[ $(sh $1 $files) == A ]
还有其他杂项错误,例如遗失then
并且]
之前没有空格。
<强>改进:强>
您应该正确引用所有内容,以防止无意中的单词拆分和全局扩展。
[ "$(sh "$1" "$files")" == A ]
让我们用$1
替换$script
,用$files
替换$file
。
[ "$(sh "$script" "$file")" == A ]
如果脚本顶部有一个像#!/bin/bash
那样合适的shebang行,那么就不需要显式调用sh
。
[ "$("$script" "$file")" == A ]
这一切都很棒。现在你有这样的事情:
if [ "$("$script" "$file")" == A ]; then
aCount=$((aCount+1))
elif [ "$("$script" "$file")" == B ]; then
bCount=$((bCount+1))
elif [ "$("$script" "$file")" == C ]; then
cCount=$((cCount+1))
elif [ "$("$script" "$file")" == D ]; then
dCount=$((dCount+1))
else
fCount=$((fCount+1))
fi
非常重复,不是吗?我们来试试case
语句。
case "$("$script" "$file")" in
A) aCount=$((aCount+1));;
B) bCount=$((bCount+1));;
C) cCount=$((cCount+1));;
D) dCount=$((dCount+1));;
*) fCount=$((fCount+1));;
esac
那个案例陈述仍然很复杂。让我们分解它以便更容易解析。
grade=$("$script" "$file")
case $grade in
...
esac
变量名应该是小写的。大写的名称是为shell保留的,所以最好不要使用它们。将COUNT
更改为count
。
我们分别将ARG
和ARG2
重命名为script
和dir
。有意义的名字使一切更容易阅读。
var=$((var+1))
可简化为((var += 1))
或((var++))
。
最终结果:
script=$1
dir=$2
check=0
aCount=0
bCount=0
cCount=0
dCount=0
fCount=0
if ((check == 0)); then
for file in "$dir"/*; do
grade=$("$script" "$file")
case $grade in
A) ((aCount++));;
B) ((bCount++));;
C) ((cCount++));;
D) ((dCount++));;
*) ((fCount++));;
esac
done
fi
echo "A: $aCount"
echo "B: $bCount"
echo "C: $cCount"
echo "D: $dCount"
echo "F: $fCount"
答案 1 :(得分:2)
@ John Kugelman上面做了伟大的工作。换句话说 -
declare -A count # count is an array
for file in "$dir"/* # skipping assignments, and $check
do grade=$("$script" "$file") # grab the output as $grade
case $grade in # look up its value
[A-D]) (( count[$grade]++ ));; # use as-is for a-d
*) (( count['F']++ ));; # throw everything else in f
esac
done
for g in A B C D F # then for a-f (known values)
do echo "$g: "${count[$g]} # pull the counts
done