英文:
How to get max and min values in linux shell with multiple possibilities?
问题
这个shell脚本获取了最大和最小值,但我想在有重复值时获取这些值以及相关的学生。
代码:
#!/bin/sh
Notamax=0
Notamin=0
alumneMax=''
alumneMin=''
while IFS=';' read alumne nota
do
(( nota > Notamax )) && Notamax=$nota alumneMax="$alumneMax $alumne $nota"
(( nota < Notamin || Notamin == 0)) && Notamin=$nota alumneMin="$alumneMin $alumne $nota"
done < notas.txt
echo "Max:$alumneMax"
echo "Min:$alumneMin"
notas.txt
pepe;5
marcos;7
marta;70
luis;70
ana;5
期望输出
Max: marta 70, luis 70
Min: pepe 5, ana 5
你可以使用上述修改后的代码来实现期望的输出。
英文:
This shell script gets me the max and min values, but I would like to get those values and the associated students when there are repeats.
Code:
#!/bin/sh
Notamax=0
Notamin=0
alumneMax=''
alumneMin=''
while IFS=";" read alumne nota
do
(( nota > Notamax )) && Notamax=$nota alumneMax=$alumne
(( nota < Notamin || Notamin == 0)) && Notamin=$nota alumneMin=$alumne
done <notas.txt
echo "Nota maxima $Notamax ** Alumnos con nota maxima: $alumneMax"
echo "Nota minima $Notamin ** Alumnos con nota minima: $alumneMin"
notas.txt
pepe;5
marcos;7
marta;70
luis;70
ana;5
Actual output
Nota maxima 70 ** Alumnos con nota maxima: marta
Nota minima 5 ** Alumnos con nota minima: pepe
Desired output
Max: marta 70, luis 70
Min: pepe 5, ana 5
How could I achieve it?
答案1
得分: 5
This is both easier and more versatile with Awk. See also Bash while read
loop extremely slow compared to cat
, why?
$2==max { maxa = maxa ", " $1 " " $2 }
$2==min { mina = mina ", " $1 " " $2 }
$2>max { max = $2; maxa = $1 " " $2 }
$2<min { min = $2; mina = $1 " " $2 }
END { print "Max:", maxa
print "Min:", mina }' notas.txt
Your output format is somewhat noisy; I would personally prefer a less redundant and more machine-readable display.
The awk
tag info page has links to basic learning resources. Learning the fundamentals of the language is quick and easy (give it an hour and you'll already have a good idea).
英文:
This is both easier and more versatile with Awk. See also Bash while read
loop extremely slow compared to cat
, why?
awk -F ';' 'NR==1 { min = max = $2; mina = maxa = $1 " " $2; next }
$2==max { maxa = maxa ", " $1 " " $2 }
$2==min { mina = mina ", " $1 " " $2 }
$2>max { max = $2; maxa = $1 " " $2 }
$2<min { min = $2; mina = $1 " " $2 }
END { print "Max:", maxa
print "Min:", mina }' notas.txt
Your output format is somewhat noisy; I would personally prefer a less redundant and more machine-readable display.
The awk
tag info page has links to basic learning resources. Learning the fundamentals of the language is quick and easy (give it an hour and you'll already have a good idea).
答案2
得分: 3
以下是翻译好的部分:
- 如果我们需要坚持使用
bash
...
对OP目前的代码做一些更改:
NotaMax=0
NotaMin=0
while IFS=";" read -r alumne nota
do
(( nota == NotaMax )) && alumneMax="${alumneMax}, ${alumne} ${NotaMax}"
(( nota > NotaMax )) && NotaMax=$nota alumneMax="Max: ${alumne} ${NotaMax}"
(( nota == NotaMin )) && alumneMin="${alumneMin}, ${alumne} ${NotaMin}"
(( nota < NotaMin || NotaMin == 0 )) && NotaMin=$nota alumneMin="Min: ${alumne} ${NotaMin}"
done < notas.txt
echo "${alumneMax}"
echo "${alumneMin}"
- 使用一对数组和匹配的 namerefs(namerefs 需要
bash 4.2+
):
NotaMax=0
NotaMin=0
while IFS=";" read -r alumne nota
do
(( nota == NotaMax )) && alumneMax+=("${alumne}")
(( nota > NotaMax )) && NotaMax=$nota alumneMax=("${alumne}")
(( nota == NotaMin )) && alumneMin+=("${alumne}")
(( nota < NotaMin || NotaMin == 0)) && NotaMin=$nota alumneMin=("${alumne}")
done < notas.txt
for op in Max Min
do
pfx="$op: "
declare -n oparr="alumne${op}"
declare -n opval="Nota${op}"
for alumne in "${oparr[@]}"
do
printf "%s%s %s" "$pfx" "$alumne" "$opval"
pfx=", "
done
echo ""
done
这两者都会生成:
Max: marta 70, luis 70
Min: pepe 5, ana 5
英文:
If we need to stick with bash
...
Making a few changes to OP's current code:
NotaMax=0
NotaMin=0
while IFS=";" read -r alumne nota
do
(( nota == NotaMax )) && alumneMax="${alumneMax}, ${alumne} ${NotaMax}"
(( nota > NotaMax )) && NotaMax=$nota alumneMax="Max: ${alumne} ${NotaMax}"
(( nota == NotaMin )) && alumneMin="${alumneMin}, ${alumne} ${NotaMin}"
(( nota < NotaMin || NotaMin == 0 )) && NotaMin=$nota alumneMin="Min: ${alumne} ${NotaMin}"
done < notas.txt
echo "${alumneMax}"
echo "${alumneMin}"
Using a pair of arrays and matching namerefs (namerefs require bash 4.2+
):
NotaMax=0
NotaMin=0
while IFS=";" read -r alumne nota
do
(( nota == NotaMax )) && alumneMax+=("${alumne}")
(( nota > NotaMax )) && NotaMax=$nota alumneMax=("${alumne}")
(( nota == NotaMin )) && alumneMin+=("${alumne}")
(( nota < NotaMin || NotaMin == 0)) && NotaMin=$nota alumneMin=("${alumne}")
done < notas.txt
for op in Max Min
do
pfx="$op: "
declare -n oparr="alumne${op}"
declare -n opval="Nota${op}"
for alumne in "${oparr[@]}"
do
printf "%s%s %s" "$pfx" "$alumne" "$opval"
pfx=", "
done
echo ""
done
Both of these generate:
Max: marta 70, luis 70
Min: pepe 5, ana 5
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论