Skip to main content
doh
Source Link
user313992
user313992

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keepkept in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of a WORD token when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar).

After a command line was parsed, it will be expanded, and as part of the expansions, any compound assignment (WORD which was marked with W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will then be passed as an argument to a builtin like declare. But if declare, after all the expansions, gets an argument of the form var=(...), it will parse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keep in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of a WORD token when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar).

After a command line was parsed, it will be expanded, and as part of the expansions, any compound assignment (WORD which was marked with W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will then be passed as an argument to a builtin like declare. But if declare, after all the expansions, gets an argument of the form var=(...), it will parse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag kept in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of a WORD token when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar).

After a command line was parsed, it will be expanded, and as part of the expansions, any compound assignment (WORD which was marked with W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will then be passed as an argument to a builtin like declare. But if declare, after all the expansions, gets an argument of the form var=(...), it will parse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('
correct the awkward wording
Source Link
user313992
user313992

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keep in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of a WORDs token when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar).

After a command line was parsed, it will be expanded, and as part of the expansions, any compound assignment (WORD which was marked as a compound assignmentwith (W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will be then be passed as an argument to a builtin like declare. But if declare, after all the expansions, gets an argument of the form var=(...), it will parse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keep in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of WORDs when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar).

After a command line was parsed, it will be expanded, and as part of the expansions, any WORD which was marked as a compound assignment (W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will be then passed as an argument to a builtin like declare. But if declare, after all the expansions, gets an argument of the form var=(...), it will parse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keep in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of a WORD token when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar).

After a command line was parsed, it will be expanded, and as part of the expansions, any compound assignment (WORD which was marked with W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will then be passed as an argument to a builtin like declare. But if declare, after all the expansions, gets an argument of the form var=(...), it will parse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('
added 366 characters in body
Source Link
user313992
user313992

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keep in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of WORDs when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar). 

After a command line was parsed, any assignment used by such a builtinit will be expanded to its variable name, and as part of the expansions, any WORD which was marked as a compound assignment (W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will be then passed as an argument;argument to a builtin like declare. But if it was quoteddeclare, it'safter all the builtin itself whichexpansions, gets an argument of the form var=(...), it will reparseparse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keep in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of WORDs when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment. After a command line was parsed, any assignment used by such a builtin will be expanded to its variable name which will be passed as an argument; if it was quoted, it's the builtin itself which will reparse and expand it.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('

tl;dr; I think it's just a syntax quirk, and you shouldn't presume some grand design behind it.

Bash is using a bison/yacc-generated parser, but just like with many other languages (C, perl, etc), it's not a "clean" parser, but it's also keeping some state separate/parallel to the grammar in the parser_state variable.

A flag keep in that state variable is PST_ASSIGNOK. That will be set when some builtin which was parsed as a WORD token had ASSIGNMENT_BUILTIN in its flags.

Such "assignment builtins" are local, typeset, declare, alias, export and readonly.

The PST_ASSIGNOK will direct the parser to consider parentheses as part of WORDs when used after an assignment at the right of such a builtin. But it will NOT change the rules which determine whether the current token is actually an assignment: Since ${foo}=(...) is not an acceptable assignment, it will not be parsed as a single word, and the parentheses will trigger a syntax error just like in echo foo(bar). 

After a command line was parsed, it will be expanded, and as part of the expansions, any WORD which was marked as a compound assignment (W_COMPASSIGN) like var=(1 2) will be performed and replaced with var, which will be then passed as an argument to a builtin like declare. But if declare, after all the expansions, gets an argument of the form var=(...), it will parse and expand it itself again.

So, varname=foo; declare "$var=(1 2 3)" may be similar to declare foo='(1 2 3)'. Or to declare foo=(1 2 3), depending on whether the variable was already defined:

$ 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")

I don't think it's a good idea to rely on this corner case:

$ 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 `('
expand a bit
Source Link
user313992
user313992
Loading
clarify
Source Link
user313992
user313992
Loading
clarify
Source Link
user313992
user313992
Loading
Source Link
user313992
user313992
Loading