использование bash для печати индекса максимального значения в массиве

#linux #bash

#linux #bash

Вопрос:

Я пытаюсь напечатать значение индекса максимального значения в массиве. Я написал что-то вроде этого:

 my_array=( $(cat /etc/grub.conf | grep title | cut -d " " -f 5,7 | tr -d '()'|cut -c1-6) )
echo "${my_array[*]}" | sort -nr | head -n1
max=${my_array[0]}
for v in ${my_array[@]}; do
    if (( $v > $max )); then max=$v; fi;
done
echo $max
  

Вывод этого скрипта выглядит следующим образом:

 4.9.85 4.9.38
./grub_update.sh: line 6: ((: 4.9.85 > 0 : syntax error: invalid arithmetic operator (error token is ".9.85 > 0 ")
./grub_update.sh: line 6: ((: 4.9.38 > 0 : syntax error: invalid arithmetic operator (error token is ".9.38 > 0 ")
0
  

Требование: Я хочу запросить grub.conf и прочитать строку Kenrnel, за которой следует значение индекса последней версии ядра в массиве

 kernel /boot/vmlinuz-4.9.38-16.35.amzn1.x86_64 root=LABEL=/ console=tty1 console=ttyS0 selinux=0
  

Комментарии:

1. Bash не может сравнить 4.9.85 с 0… похоже, вам нужно немного больше, чем простой цикл.

2. извините, я только что обновил код, в настоящее время я могу получить вывод, но он выдает меньшее значение, пока я ищу большее число

3. Если вы хотите выполнить сортировку по версии, для этого используется аргумент GNU sort -V .

4. Кстати, array=( $(...) ) это антипаттерн; смотрите BashPitfalls #50 .

Ответ №1:

Комментарии в коде:

 # our array
arr=( 
     1.1.1  # first element
     2.2.2 
     4.9.85 # third element, the biggest
     4.9.38 
)

# print each array element on a separate line
printf "%sn" "${arr[@]}" | 
# substitute the point to a space, so xargs can process it nicely
tr '.' ' ' |
# add additional zeros to handle single digit and double digit kernel versions
xargs -n3 printf "%dddn" |
# add line numbers as the first column
nl -w1 |
# number sort via the second column
sort -k2 -n |
# get the biggest column, the latest
tail -n1 |
# get the first field, the line/index number
cut -f1
  

Он выведет:

 3
  

Живой код доступен на tutorialspoint.

Ответ №2:

  • Вы можете выполнять сравнения строк, если цифры выровнены.
  • printf можно выровнять цифры
 data=(
    4.9.85
    4.9.38
    3.100.20.2
    4.12.2.4.5
    4.18.3
)

findmax(){
    local cur
    local best=''
    local ans

    for v in "$@"; do
        cur="$(
            # split on dots
            IFS=.
            printf 'sssss' $v
        )"
        # note: sort order is locale-dependent
        if [[ $cur > $best ]]; then
            ans="$v"
            best="$cur"
        fi
    done
    echo "$ans"
}

echo "max = $(findmax "${data[@]}")"