获取 Linux Shell 中最大和最小值的方法有多种可能性。

huangapple go评论62阅读模式
英文:

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=&#39;&#39;
alumneMin=&#39;&#39;
while IFS=&quot;;&quot; read alumne nota
do
	(( nota &gt; Notamax )) &amp;&amp; Notamax=$nota alumneMax=$alumne
	(( nota &lt; Notamin || Notamin == 0)) &amp;&amp; Notamin=$nota alumneMin=$alumne
done &lt;notas.txt
echo &quot;Nota maxima $Notamax ** Alumnos con nota maxima: $alumneMax&quot;
echo &quot;Nota minima $Notamin ** Alumnos con nota minima: $alumneMin&quot;

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 &#39;;&#39; &#39;NR==1 { min = max = $2; mina = maxa = $1 &quot; &quot; $2; next }
$2==max { maxa = maxa &quot;, &quot; $1 &quot; &quot; $2 }
$2==min { mina = mina &quot;, &quot; $1 &quot; &quot; $2 } 
$2&gt;max { max = $2; maxa = $1 &quot; &quot; $2 }
$2&lt;min { min = $2; mina = $1 &quot; &quot; $2 }
END { print &quot;Max:&quot;, maxa
  print &quot;Min:&quot;, mina }&#39; 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

以下是翻译好的部分:

  1. 如果我们需要坚持使用 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}"
  1. 使用一对数组和匹配的 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=&quot;;&quot; read -r alumne nota
do
    (( nota == NotaMax ))                 &amp;&amp;               alumneMax=&quot;${alumneMax}, ${alumne} ${NotaMax}&quot;
    (( nota  &gt; NotaMax ))                 &amp;&amp; NotaMax=$nota alumneMax=&quot;Max: ${alumne} ${NotaMax}&quot;
    (( nota == NotaMin ))                 &amp;&amp;               alumneMin=&quot;${alumneMin}, ${alumne} ${NotaMin}&quot;
    (( nota  &lt; NotaMin || NotaMin == 0 )) &amp;&amp; NotaMin=$nota alumneMin=&quot;Min: ${alumne} ${NotaMin}&quot;
done &lt; notas.txt

echo &quot;${alumneMax}&quot;
echo &quot;${alumneMin}&quot;

Using a pair of arrays and matching namerefs (namerefs require bash 4.2+):

NotaMax=0
NotaMin=0

while IFS=&quot;;&quot; read -r alumne nota
do
    (( nota == NotaMax ))                &amp;&amp;               alumneMax+=(&quot;${alumne}&quot;)
    (( nota  &gt; NotaMax ))                &amp;&amp; NotaMax=$nota alumneMax=(&quot;${alumne}&quot;)
    (( nota == NotaMin ))                &amp;&amp;               alumneMin+=(&quot;${alumne}&quot;)
    (( nota  &lt; NotaMin || NotaMin == 0)) &amp;&amp; NotaMin=$nota alumneMin=(&quot;${alumne}&quot;)
done &lt; notas.txt

for op in Max Min
do
    pfx=&quot;$op: &quot;
    declare -n oparr=&quot;alumne${op}&quot;
    declare -n opval=&quot;Nota${op}&quot;

    for alumne in &quot;${oparr[@]}&quot;
    do
        printf &quot;%s%s %s&quot; &quot;$pfx&quot; &quot;$alumne&quot; &quot;$opval&quot;
        pfx=&quot;, &quot;
    done
    echo &quot;&quot;
done

Both of these generate:

Max: marta 70, luis 70
Min: pepe 5, ana 5

huangapple
  • 本文由 发表于 2023年5月15日 00:19:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76248531.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定