我正在尝试使用二进制搜索来显示学生的成绩(如果他们在数组中)。搜索没有问题,但是,显然我没有正确比较条件语句中的数据。无论输入什么名称,elif
都会运行。我所比较的至少一个值似乎存在问题。
这是存储在数组中的内容:
Ann:A
Bob:C
Cindy:B
Dean:F
Emily:A
Frank:C
Ginger:D
Hal:B
Ivy:A
Justin:F
Karen:D
这是我的剧本。
#!/bin/bash
# Create array from student list
studentArray=($(cat ./studentList.dat))
# Ask for student name
echo "Enter Student Name"
studentName=$(read)
# variable to store if a student has been found
studentFound="false"
# variable to store student grade
studentGrade=""
# start and end index of the studentArray
START=0
END=$((${#studentArray[@]}-1))
# binary search
while [ "$START" -le "$END" ]; do
MIDDLE=$((START+((END-START)/2)))
middleItem=$(echo ${studentArray[$MIDDLE]} | cut -d: -f1)
if [ "$studentName" = "$middleItem" ]; then
studentFound="true"
studentGrade=$(echo ${studentArray[$MIDDLE]} | cut -d: -f2)
break
elif [[ "$studentName" < "$middleItem" ]]; then
((END=MIDDLE-1))
else
((START=MIDDLE+1))
fi
done
if [ "$studentFound" == "true" ]; then
echo $studentGrade
else
echo "Sorry, there is no student by that name"
fi
答案 0 :(得分:2)
此修复程序的简短版本:studentName=$(read)
不起作用,请改用read -r studentName
。
更长的修复程序,包括一些指针:
使用
将文件读取到数组中mapfile -t studentArray < studentList.dat
这避免了您可能会看到的未引用扩展名带来的意外。
echo
和read
可以在Bash中组合:
read -rp "Enter Student Name: " studentName
-r
是为了避免反斜杠的解释,而-p
可让您指定提示。
避免使用所有大写的变量名:它们更可能与shell和环境变量冲突。而且,Bash具有提供算术上下文的条件构造:
while ((start <= end)); do
middle=$((start + (end-start)/2))
...
要获取用冒号分隔的字符串的第一部分,可以使用参数扩展:
middleItem=${studentArray[middle]%:*}
请注意,由于索引是算术上下文,因此不需要$
。
冒号分隔的字符串的第二部分也是如此:
studentGrade=${studentArray[middle]#*:}
总而言之:
#!/usr/bin/env bash
# Create array from student list
mapfile -t studentArray < studentList.dat
# Ask for student name
read -rp "Enter Student Name: " studentName
# Variable to store if a student has been found
studentFound="false"
# Start and end index of the studentArray
start=0
end=$((${#studentArray[@]} - 1))
# Binary search
while ((start <= end)); do
middle=$((start + ((end - start) / 2)))
middleItem=${studentArray[middle]%:*}
if [[ $studentName == "$middleItem" ]]; then
studentFound="true"
studentGrade=${studentArray[middle]#*:}
break
elif [[ $studentName < $middleItem ]]; then
((end = middle - 1))
else
((start = middle + 1))
fi
done
if [[ $studentFound == "true" ]]; then
echo "$studentGrade"
else
echo "Sorry, there is no student by that name"
fi
答案 1 :(得分:1)
该代码错误地使用了read
。读取功能将一行读入变量,并且不打印输入行。因此,studentName=$(read)
将studentName设置为“
建议的解决方法:
read studentName
旁注:使用脚本执行的最简单的操作之一是在顶部添加'set -x',或使用bash -vx script ...
调用脚本。这将提供逐行的信息(包括变量分配),使识别问题变得容易。对于上述脚本,输出将为:
+ studentArray=($(cat ./studentList.dat))
++ cat ./studentList.dat
+ echo 'Enter Student Name'
Enter Student Name
++ read
Hal
<-- Error here -->
+ studentName=
+ studentFound=false
+ studentGrade=
显示的StudentName设置不正确。