所以我有一个主题文件夹,位于 / home / subject 中,其中包含诸如:
这些主题是文件。 并且每一个都包含带有标记的学生姓名。
例如,它将是
对于地理
和数学:
我还有一个 student文件夹,位于 / home / student 中,目前为空。 这个文件夹的目的是放在其中:
这是我的代码:
rm /home/student/*
for subjectFile in /home/subject/*; do
awk -v subject="$(basename "$subjectFile")" '{ print subject, $2 >>"/home/student/" $1 }' "$subjectFile"
done
此循环遍历主题文件夹内的所有主题文件。 $ subjectFile值类似于:
然后,获取每个主题文件的基本名称:
然后在通过主题文件第一列获得的我的学生姓名中打印第二列的结果,标记号:因此,在本示例中,对于主题< strong>地理,我会得到 Matthew 。
我也不想简单地无限追加结果,但是每次运行此脚本时覆盖以前的结果,所以我输入了:rm / home / student / *,以擦除任何结果学生档案,然后再进行追加。
这很好用。
但是我有一个请求,
如果未定义该学生的学科标记,我该如何使其用0代替?? 一个学生没有针对某个特定学科获得任何分数,而其他人则获得了分数?
例如:
对于地理
和数学:
对于 Elena , 这将在学生文件夹的内部创建一个Elena文件:
答案 0 :(得分:2)
尝试:这将在/tmp
中创建一棵小树:
cd /tmp && tar -zxvf <(base64 -d <<eof
H4sIAFUFUFwAA+3XXU6EMBQF4D6ziu7A/l2uLsBHE7eAYwUMghlKnNm9EKfEEHUyBpg4nu+lJJDQ
5HBK226KpqmuxJJUj4mGUTOpz2MktHXG9RdEWiitrWUhadFZHXRtyLZSiidflbsfnjt2/49qP/Jv
u4dnvwnLfAcn5K9JuT5/w0zIfw2T/F+yUMz+jiHg1Lnv87c09j9l0+dvU3JCqtln8oV/nv9dFkLh
36RWyW3l60zqm+S+KCspNSfnnhwsbtJ/X+dV2c68BBzvfzr2nw33/XeWUvR/DWP/WcYFgOICcI0F
4OJN+p/7Jt9mr8V+znec8P8/7P8cK4v+r2HsP8X6u1h/Qv0vX+x/6B59ff7znyFNw/5fGZz/AQAA
AAAAAAAAAAB+7R1PsalnACgAAA==
eof
)
这将创建(并且由于tar命令中的-v
标志而在终端中打印):
school/
school/subject/
school/subject/math
school/subject/english
school/subject/geography
school/student/
cd /tmp/school/subject/
grep . * | sort -t: -k2
将呈现:
geography:Elena 14
english:Elena 15
math:Elena 19
math:Matthew 10
geography:Matthew 15
english:Matthew 17
geography:Phil 15
math:Phil 17
english:Phil 18
cd /tmp/school
rm student/*
for file in subject/*;do
subj=${file##*/}
while read student note ;do
echo >>student/${student,,} ${subj^} $note
done < $file
done
注意::使用${VARNAME^}
高位第一个字符,使用${VARNAME,,}
低位所有字符串。因此,文件名是小写字母,并且主题在学生文件中变为大写。
那么现在:
ls -l student
total 12
-rw-r--r-- 1 user user 32 jan 29 08:57 elena
-rw-r--r-- 1 user user 32 jan 29 08:57 matthew
-rw-r--r-- 1 user user 32 jan 29 08:57 phil
和
cat student/phil
English 18
Geography 15
Math 17
for file in student/*;do
for subj in subject/*;do
subj=${subj##*/}
grep -q ^${subj^}\ $file || echo ${subj^} 0 >> $file
done
done
可以对此进行测试(这将在所有文件中随机删除0或1个标记):
for file in subject/*;do
((val=1+(RANDOM%4)))
((val<4)) && sed ${val}d -i $file
done
然后运行:
cd /tmp/school
rm student/*
for file in subject/*;do
subj=${file##*/}
while read student note ;do
echo >>student/${student,,} ${subj^} $note
done < $file
done
for file in student/*;do
for subj in subject/*;do
subj=${subj##*/}
grep -q ^${subj^}\ $file || echo ${subj^} 0 >> $file
done
done
好,现在:
grep ' 0$' student/*
student/matthew:Geography 0
注意::由于我$RANDOM
的使用,您的测试结果可能有所不同;-)
第一步:建立学生名单,然后立即以0
表示法创建学生文件:
cd /tmp/school
rm student/*
declare -A students
for file in subject/* ;do
while read student mark ;do
[ "$student" ] && students[$student]=
done <$file
done
for file in subject/*;do
class=(${!students[@]})
while read student mark ;do
subj=${file##*/}
echo >> student/${student,,} ${subj^} $mark
class=(${class[@]/$student})
done <$file
for student in ${class[@]};do
echo >> student/${student,,} ${subj^} 0
done
done
为了娱乐,有很多 bashisms 且没有创建文件,但有一个漂亮的转储工具:
#!/bin/bash
declare -A students
declare subjects=() sublen=0 stdlen=0
for file in subject/* ;do # read all subject files
subj=${file##*/}
subjects+=($subj) # Add subject to array
sublen=$(( ${#subj} > sublen ? ${#subj} : sublen )) # Max subject string len
declare -A mark_$subj # Create subject's associative array
while read student mark ;do
stdlen=$(( ${#student} > $stdlen ? ${#student} : stdlen ))
[ "$student" ] && { # Skip empty lines
((students[$student]++)) # Count student's marks
printf -v mark_$subj[$student] "%d" $mark # Store student's mark
}
done <$file
done
printf -v formatstr %${#subjects[@]}s; # prepare format string for all subjects
formatstr="%-${stdlen}s %2s ${formatstr// / %${sublen}s}"
printf -v headline "$formatstr" Student Qt "${subjects[@]}"
echo "$headline" # print head line
echo "${headline//[^ ]/-}" # underscore head line
for student in ${!students[@]};do # Now one line by student...
marks=() # Clear marks
for subject in ${subjects[@]};do
eval "marks+=(\${mark_$subject[\$student]:-0})" # Add subject mark or 0
done
printf "$formatstr\n" $student ${students[$student]} ${marks[@]}
done
这可能会打印出以下内容:
Student Qt english geography math
------- -- ------- --------- ----
Phil 2 18 15 0
Matthew 3 17 15 10
Elena 2 0 14 19
此脚本是为 bem v4.4.12 构建的,并已在 bem v5.0 中进行了测试。
>您可以下载更大的演示脚本:scholl-averages-demo.sh(在浏览器as text .txt中查看)。
始终纯bash 不带叉子,但带
。
Student Qt art biology english geography history math Average
------- -- --- ------- ------- --------- ------- ---- -------
Elena 5 12 0 15 14 17 19 12.83
Iñacio 6 12 15 19 18 12 14 15.00
Matthew 5 19 18 17 15 17 0 14.33
Phil 5 15 19 18 0 13 17 13.67
Renée 6 14 19 18 17 18 15 16.83
Theresa 5 17 14 0 12 17 18 13.00
William 6 17 17 15 15 13 14 15.17
------- -- --- ------- ------- --------- ------- ---- -------
Avgs 7 15.14 14.57 14.57 13.00 15.28 13.86 14.40
答案 1 :(得分:1)
我会这样做。首先为每个学生制作空文件:
cat /home/subject/* | cut -d' ' -f1 | sort -u | while read student_name; do > /home/students/$student ; done
然后,我将逐一检查并添加标记:
for student in `ls /home/students` ; do
for file in /home/subjects/* ; do
subject="`basename $file`"
mark="`egrep "^$student [0-9]+" $file | cut -d' ' -f2`"
if [ -z "$mark" ]; then
echo "$subject 0" >> /home/students/$student
else
echo "$subject $mark" >> /home/students/$student
fi
done
done
反正如此