Команда Declare и расширение оболочки

Я успешно выполнил команду 7z x <source.zip>.

Версия:

p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,[...])

Потенциально важная среда:

LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8
LC_CTYPE=UTF-8

Он смог распаковать все файлы с 8 -битными символами в именах файлов, причем некоторые из этих символов были пропущены, а некоторые искажены.

5
16.03.2020, 11:46
1 ответ

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

Bash использует сгенерированный bison/yacc -синтаксический анализатор , но, как и во многих других языках (C, perl и т. д. ), это не "чистый" синтаксический анализатор, а он также сохраняет некоторое состояние отдельно/параллельно грамматике в переменной parser_state.

В этой переменной состояния хранится флаг PST_ASSIGNOK. Это будет установлено, когда некоторые встроенные функции, которые были проанализированы как токен WORD, имели ASSIGNMENT_BUILTINв своих флагах.

Такими "встроенными функциями назначения" являются local, typeset, declare, alias, exportи readonly.

PST_ASSIGNOKпредписывает синтаксическому анализатору рассматривать круглые скобки как часть маркера WORD, когда они используются после присваивания справа от такой встроенной функции. Но это НЕ изменит правила, которые определяют, является ли текущий токен на самом деле присвоением :. Поскольку ${foo}=(...)не является приемлемым присвоением, оно не будет анализироваться как одно слово, а круглые скобки вызовут синтаксис ошибка точно так же, как в echo foo(bar).

После синтаксического анализа командной строки она будет расширена , и как часть расширений любое составное назначение (WORD, помеченное как W_COMPASSIGN), например var=(1 2), будет выполнено и заменено с var, который затем будет передан в качестве аргумента встроенной функции, например declare. Но если declareпосле всех расширений получит аргумент вида var=(...), то он снова сам его разберет и расширит.

Итак, varname=foo; declare "$var=(1 2 3)"может быть похоже на declare foo='(1 2 3)'. Или к declare foo=(1 2 3), в зависимости от того, была ли переменная уже определена:

$ declare 'foo=(1 2 3)'; typeset -p foo
declare -- foo="(1 2 3)"
$ declare foo=(1); typeset -p foo
declare -a foo=([0]="1")
$ declare 'foo=(1 2 3)'; typeset -p foo
declare -a foo=([0]="1" [1]="2" [2]="3")

Я не думаю, что стоит полагаться на этот крайний случай:

$ declare 'bar=(1 ( )'; typeset -p bar
declare -- bar="(1 ( )"
$ declare bar=(1); typeset -p bar
declare -a bar=([0]="1")
$ declare 'bar=(1 ( )'; typeset -p bar
bash: syntax error near unexpected token `('
7
28.04.2021, 23:20

Теги

Похожие вопросы