Как избавиться от унарного оператора, ожидаемого в сценарии оболочки

#shell

Вопрос:

Почему я продолжаю получать «Ожидаемый унарный оператор», даже если мой код выполняется и выводится правильно? Это просто простая сортировка пузырьков массива.

 #!/bin/bash

declare -a array
hold=0

echo "Input length of array: "
read length

for((i = 0; i < length; i  ))
do
        echo "Enter number: "
        read input
        array =($input)
done

echo " "
echo "Elements in array: "
echo "${array[*]}"

echo " "
echo "Sorted Array"

for((i = 0; i < $length; i  ))
do
        for((j = 0; j < $length; j  ))
        do
                if [ ${array[j]} -gt ${array[$((j 1))]} ]
                then
                        hold=${array[j]}
                        array[$j]=${array[$((j 1))]}
                        array[$((j 1))]=$hold
                fi
        done
done

echo "Sorted Elements in array: "
echo "${array[*]}"
 

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

1. Пожалуйста, отформатируйте свой код в вопросе, прочитайте минимальные требования, как задавать вопросы, так как перед тем, как помочь вам, я должен исправить ваш пример кода

2. Реализация пузырьковой сортировки — это пустая трата времени. Вы не пишете подобные программы в сценарии оболочки: вы пишете код, который запускает другие программы.

Ответ №1:

Используйте (( )) для математических операций, код будет более читаемым, поскольку вам не нужны специальные символы https://github.com/koalaman/shellcheck/wiki/SC2219

ваше проблемное место: if [ ${array[j]} -gt ${array[$((j 1))]} ] заменить на if (( array[j] > array[j 1] ))

Улучшенная версия вашего кода :

 #!/bin/bash

declare -a array 
declare hold=0

# echo "Input length of array: " 
#read length

#for (( i = 0; i < length; i   )); do 
#   echo "Enter array number: $i" ;
#   read input 
#   array =($input) 
# done

array=(6 7 2 3 8 9)
length=${#array[@]}

echo "************************"
echo "Elements in array: " 
echo "${array[*]}"
echo "************************"

for (( i = 0; i < length; i   )); do    
    
    for (( j = 0; j < length -1 ; j   )); do         
        #echo "iteration i/j - $i/$j ${array[*]} "                      
        if (( array[j] > array[j 1] )); then            
            hold=array[j]
            array[j]=array[j 1]
            array[j 1]=hold
            echo "change ${array[*]} " 
        fi 

    done 
done

echo "************************"
echo "Sorted Elements in array: " 
echo "${array[*]}"
echo "************************"
 

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

1.Shellcheck предупреждает Вместо let expr , предпочитаю (( expr )) .

2. Вам не нужно let или ((...)) для назначений. Индексы массива вычисляются в арифметическом контексте. array[j]=array[j 1] работает нормально.

3. Аргумент без кавычек to let подлежит разделению на слова и расширению глобуса, как и любая другая обычная команда. Надуманный, но действительный пример: array=(5 7 9); j=0; array1=42; touch "arrayj=array1"; set -x; let array[j]=array[j 1]; set x; declare -p array arrayj; ((array[j] = array[j 1])); declare -p array arrayj

4. проверено здесь: replit.com/languages/bash вот что у меня получилось: main.sh : строка 27: j 1: превышен уровень рекурсии выражения (маркер ошибки — «j 1»)

5. Вы упустили важное исправление: завершение внутреннего цикла до j того, как оно станет слишком большим.