Использование «объявить» в Zsh

Я слежу за этой темой: https://stackoverflow.com/a/19742842/5057251 для набора (или объявления) в ZSH, а не в BASH.

#Declare (or typeset) an array of integers
#declare -ai int_array
typeset -ai int_array
int_array=(1 2 3)
echo "${int_array[@]}"

потом

# Attempt to change 1st element to string. (expect to fail)
int_array[1] = "Should fail" || echo "error: ${LINENO}"
echo "${int_array[@]}"

Bash находит ошибку, изящно сообщает об ошибке и lineno, печатает:

1 2 3

Но Zsh принимает, печатает:

Should fail 2 3

Не знаю, почему по-другому.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
2 786
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Здесь есть две проблемы:

  1. В bash и zsh присваивание строки целочисленной переменной приводит к тому, что эта строка оценивается как арифметическое выражение. Таким образом, это не ошибка:

    $ typeset -i foo
    $ foo = "bar"
    

    Если бы bar была переменной, ранее установленной в арифметическое выражение, то расширение bar было бы оценено как таковое:

    $ bar=10+2
    $ typeset -i foo
    $ foo = "bar"
    $ echo "$foo"
    12
    

    Ошибка в вашем задании, конечно же, в том, что нет возможности так расширить Should fail. Если бы это было, скажем, Should - fail (например, арифметическое выражение, вычитающее значение двух переменных Should и fail, оно все равно работало бы:

    $ foo = "Should - fail"
    $ echo "$foo"
    0
    
  2. Вторая проблема заключается в том, что ничто в документы зш не указывает на то, что -i может быть установлено для всего массива, поэтому -a в -ai игнорируется:

    bash-5.0$ typeset -ai foo
    bash-5.0$ declare -p foo
    declare -ai foo=([0] = "0")  # the previous value was retained in the array
    

    против ЗШ:

    % typeset -ai foo
    % foo[1]=10
    % foo[2]=20
    % declare -p foo
    typeset -i foo=20  # treated as a normal variable, not array
    

    То, что вы видите, по сути int_array переобъявляется как массив (без каких-либо квалификаторов), когда вы делаете int_array=(1 2 3):

    % foo=(1 2 3)
    % declare -p foo
    typeset -a foo=( 1 2 3 )
    

Сложный. declare -p foo # очень полезно посмотреть, что думает оболочка

jim rothstein 11.04.2019 09:07

Использование zsh typeset может дать несколько возможных результатов:
- ошибок нет, работает (ага!).
- ошибки, сбой скрипта (исправить!).
- ошибок нет, но поведение непредвиденный. (почесать голову)

В качестве примера последней категории это не приводит к ошибкам, но typeset -p показывает, что -i игнорируется.

{                                                                                                                                                                        
unset int_array                                                                                                                                                          
typeset -ia int_array                                                                                                                                                    
int_array=(1 2 3)                                                                                                                                                        
echo $? "-Point A"                                                                                                                                                       
typeset -p int_array                                                                                                                                                     

    } always {                                                                                                                                                           

echo $? "-Point B"                                                                                                                                                       
typeset -p int_array                                                                                                                                                     
(( TRY_BLOCK_ERROR=0 ))                                                                                                                                                  
}                                                                                                                                                                        
echo $? "-Point C"                                                                                                                                                       
echo "survived"                                                                                                                                                          

производит

 0 -Point A                                                                                                                                                               
 typeset -a int_array=( 1 2 3 )                                                                                                                                           
 0 -Point B                                                                                                                                                               
 typeset -a int_array=( 1 2 3 )                                                                                                                                           
 0 -Point C                                                                                                                                                               
 survived                                                                                                                                                                 

Первая строка сбрасывает int_array. Команда набора объявляет
int_array должен быть как массивом, так и целым, что не позволяет zsh. Следующий
строка присваивает int_array значение. Как говорит нам $?, ошибки нет,
но внимательное изучение финала typeset -p int_array показывает, что на самом деле
случилось.

С небольшим изменением мы можем выдавать ошибки и использовать блок always и
typeset -p чтобы узнать подробности.

{                                                                                                                                                                        
unset int_array                                                                                                                                                          
typeset -ia int_array=(1 2 3) # error                                                                                                                                    
echo $? "-Point A"                                                                                                                                                       
typeset -p int_array 

      } always {                                                                                                                                                           

echo $? "-Point B"                                                                                                                                                       
typeset -p int_array                                                                                                                                                     
(( TRY_BLOCK_ERROR=0 ))                                                                                                                                                  
}                                                                                                                                                                        
echo $? "-Point C"                                                                                                                                                       
echo "survived"                                                                                                                                                          
040_declare_version2.sh:typeset:135: int_array: inconsistent type for assignment                                                                                         
1 -Point B                                                                                                                                                               
040_declare_version2.sh:typeset:140: no such variable: int_array                                                                                                         
1 -Point C                                                                                                                                                               
survived                                                                                                                                                                 

Единственная разница в том, что int_array было присвоено значение в ошибочном операторе typeset -ia.
Это приводит к ошибкам, и скрипт переходит к always block.
(( TRY_BLOCK_ERROR=0)) позволяет продолжить выполнение сценария
и не прекращается, но об ошибке все еще сообщается в «точке C».

Чтобы проверить версию оболочки:

$SHELL --version                                                                                                                                                         
zsh 5.4.2 (x86_64-ubuntu-linux-gnu)                                                                                                                                      

Другие вопросы по теме