Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
2020-02-20 21:36 GMT+01:00, Chet Ramey : > On 2/19/20 4:03 PM, Arfrever Frehtes Taifersar Arahesis wrote: >> ${!variable@operator} does not work for variables without values. >> See empty values for all occurrences of ${!var@...} below. >> >> ${variable@A} does not work for scalar variables without values, but >> interestingly ${variable[@]@A} works for them. >> See difference between ${VAR1@A} and ${VAR1[@]@A} below. >> However neither ${variable@A} nor ${variable[@]@A} works for arrays >> without values. >> >> Both ${variable@a} and ${variable[@]@a} work for scalar variables >> without values. >> However ${variable[@]@a} does not work for arrays without values. > > Same answer as previously: maybe it should display the attributes > even thought the variable is unset. Yes, I think that @A, [@]@A, @a and [@]@a should work for unset variables. As mentioned previously, @a and [@]@a already works for unset scalar variables, and @a works for unset arrays, but [@]@a does not work for unset arrays (while it works for set arrays). Examples for @a and [@]@a: $ declare -lr VAR1 $ declare -lr VAR2=zzz $ declare -alr VAR3 $ declare -alr VAR4=(zzz zzz) $ declare -Alr VAR5 $ declare -Alr VAR6=([0]=zzz [1]=zzz) $ declare -p VAR{1,2,3,4,5,6} declare -rl VAR1 declare -rl VAR2="zzz" declare -arl VAR3 declare -arl VAR4=([0]="zzz" [1]="zzz") declare -Arl VAR5 declare -Arl VAR6=([1]="zzz" [0]="zzz" ) $ echo "${VAR1@a}" rl $ echo "${VAR1[@]@a}" rl $ echo "${VAR2@a}" rl $ echo "${VAR2[@]@a}" rl $ echo "${VAR3@a}" arl $ echo "${VAR3[@]@a}" $ echo "${VAR4@a}" arl $ echo "${VAR4[@]@a}" arl arl $ echo "${VAR5@a}" Arl $ echo "${VAR5[@]@a}" $ echo "${VAR6@a}" Arl $ echo "${VAR6[@]@a}" Arl Arl $ -- Arfrever Frehtes Taifersar Arahesis
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
Chet Ramey 2020-02-20 21:22 UTC: > On 2/19/20 7:46 PM, Arfrever Frehtes Taifersar Arahesis wrote: >> But I am not interested in any ${!varname[@]}, but instead in applying >> @operator transformations. > > OK, let's see how these work. > > Given the following > > VAR2=(aaa bbb) > varname=VAR2 > > What does > > echo ${!varname[@]@Q} > > output? > > You first have to expand `varname[@]' as an indirect reference. Since > varname is a scalar variable, varname[@] expands to the same thing as > varname, which is VAR2. Now you expand VAR2, which, since VAR2 is an > array variable, is the same as VAR2[0]. That gives you "aaa", so the > output is 'aaa'. Your explanation is convincing for varname=VAR2 but now I would expect different results for varname=VAR2[@]. Current actual results: $ VAR2=(aaa bbb) $ varname="VAR2[@]" $ echo "${VAR2@Q}" 'aaa' $ echo "${VAR2[@]@Q}" 'aaa' 'bbb' $ echo "${!varname@Q}" $ echo "${!varname[@]@Q}" $ Expected results for last 2 commands: $ echo "${!varname@Q}" 'aaa' 'bbb' $ echo "${!varname[@]@Q}" bash: ${VAR2[@][@]@Q}: bad substitution# This is example from direct usage of [@][@] $ -- Arfrever Frehtes Taifersar Arahesis
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
Chet Ramey 2020-02-20 20:41 UTC: > On 2/19/20 5:22 PM, Arfrever Frehtes Taifersar Arahesis wrote: >>> ${variable@A} does not work for scalar variables without values, but >>> interestingly ${variable[@]@A} works for them. >> >> More precisely, ${variable[@]@A} is non-empty, but not exactly correct. >> >>> See difference between ${VAR1@A} and ${VAR1[@]@A} below. >> >> ${VAR1[@]@A} is: >> declare -rl VAR1=''" >> But should be: >> declare -rl VAR1 >> As in output of 'declare -p VAR1'. > > The output is two blank lines: > > $ cat x6b > declare -lr VAR1 > > echo ${VAR1@A} > echo ${VAR1[@]@A} > $ ../bash-5.0-patched/bash ./x6b > > Even more strangely, quoting apparently matters... $ declare -lr VAR1 $ echo ${VAR1@A} $ echo ${VAR1[@]@A} $ echo "${VAR1@A}" $ echo "${VAR1[@]@A}" declare -rl VAR1='' $ declare -p VAR1 declare -rl VAR1 $ > The question is whether the unset variables should display commands to > set the attributes (@A) or display any attributes (@a). I think that it would be expected that @A prints the same as 'declare -p' for given variable. -- Arfrever Frehtes Taifersar Arahesis
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
Eli Schwartz 2020-02-20 23:49 UTC: > Your examples are all (still) broken. This would affect only 10 examples from 120, so only 8.33 % of examples, far from all examples. > You cannot use ${!ref[@]}, you need the array subscript as part of the > set value of "ref" and then indirectly refer to ref. > > $ declare -A VAR2=([foo]=bar [baz]="how interesting") > $ args "${!VAR2[@]}" > > ... > And, as predicted, if instead of using ${!ref[@]} you use > ${!varname[@]}, you get meaningful information. But I am not interested in any ${!varname[@]}, but instead in applying @operator transformations. >From `man bash`: ``` ${parameter@operator} Parameter transformation. The expansion is either a transformation of the value of parameter or information about parameter itself, de‐ pending on the value of operator. Each operator is a single letter: Q The expansion is a string that is the value of parameter quoted in a format that can be reused as input. E The expansion is a string that is the value of parameter with backslash escape sequences expanded as with the $'...' quoting mecha‐ nism. P The expansion is a string that is the result of expanding the value of parameter as if it were a prompt string (see PROMPTING be‐ low). A The expansion is a string in the form of an assignment statement or declare command that, if evaluated, will recreate parameter with its attributes and value. a The expansion is a string consisting of flag values representing parameter's attributes. If parameter is @ or *, the operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parame‐ ter is an array variable subscripted with @ or *, the operation is applied to each member of the array in turn, and the expansion is the resultant list. ``` Is there any way for using ${!variable} combined with ${variable@operator} to get useful results for multi-elemental arrays? If not, then I can still use `eval` :) . $ ARRAY=(あ い う え お) $ REF=ARRAY $ eval "echo \"\${${REF}[@]@A}\"" declare -a ARRAY=([0]="あ" [1]="い" [2]="う" [3]="え" [4]="お") $ eval "echo \"\${${REF}[@]@a}\"" a a a a a $ echo "${ARRAY[@]@A}" declare -a ARRAY=([0]="あ" [1]="い" [2]="う" [3]="え" [4]="お") $ echo "${ARRAY[@]@a}" a a a a a $ Majority (3 of 4) of bugs reported by me in this thread are unaffected by above discussion about ${!...} and are certainly still valid. -- Arfrever Frehtes Taifersar Arahesis
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
While described problems exist, there were typos in original reproduction steps. Corrected output also reveals another bug: ${!variable[@]@A} for (indexed or associative) arrays does not include indexes. Example part of output: var=VAR4 ${!var@A}:'declare -arl VAR4='zzz'' ${!var[@]@A}: 'declare -arl VAR4='zzz'' ${VAR4@A}:'declare -arl VAR4='zzz'' ${VAR4[@]@A}: 'declare -arl VAR4=([0]="zzz")' ${!var[@]@A} would be expected to be the same as ${VAR4[@]@A}. Corrected full reproduction steps with better formatting of 'for' loops: $ declare -lr VAR1 $ declare -lr VAR2=zzz $ declare -alr VAR3 $ declare -alr VAR4=(zzz) $ declare -Alr VAR5 $ declare -Alr VAR6=([0]=zzz) $ declare -p VAR{1,2,3,4,5,6} declare -rl VAR1 declare -rl VAR2="zzz" declare -arl VAR3 declare -arl VAR4=([0]="zzz") declare -Arl VAR5 declare -Arl VAR6=([0]="zzz" ) $ for operator in Q E P A a ; do > for var in VAR{1,2,3,4,5,6} ; do > echo "var=${var}" > eval "echo \"\\\${!var@${operator}}:'\${!var@${operator}}'\"" > eval "echo \"\\\${!var[@]@${operator}}: '\${!var[@]@${operator}}'\"" > eval "echo \"\\\${${var}@${operator}}:'\${${var}@${operator}}'\"" > eval "echo \"\\\${${var}[@]@${operator}}: '\${${var}[@]@${operator}}'\"" > echo > done > done var=VAR1 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR1@Q}:'' ${VAR1[@]@Q}: '' var=VAR2 ${!var@Q}:''zzz'' ${!var[@]@Q}: ''zzz'' ${VAR2@Q}:''zzz'' ${VAR2[@]@Q}: ''zzz'' var=VAR3 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR3@Q}:'' ${VAR3[@]@Q}: '' var=VAR4 ${!var@Q}:''zzz'' ${!var[@]@Q}: ''zzz'' ${VAR4@Q}:''zzz'' ${VAR4[@]@Q}: ''zzz'' var=VAR5 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR5@Q}:'' ${VAR5[@]@Q}: '' var=VAR6 ${!var@Q}:''zzz'' ${!var[@]@Q}: ''zzz'' ${VAR6@Q}:''zzz'' ${VAR6[@]@Q}: ''zzz'' var=VAR1 ${!var@E}:'' ${!var[@]@E}: '' ${VAR1@E}:'' ${VAR1[@]@E}: '' var=VAR2 ${!var@E}:'zzz' ${!var[@]@E}: 'zzz' ${VAR2@E}:'zzz' ${VAR2[@]@E}: 'zzz' var=VAR3 ${!var@E}:'' ${!var[@]@E}: '' ${VAR3@E}:'' ${VAR3[@]@E}: '' var=VAR4 ${!var@E}:'zzz' ${!var[@]@E}: 'zzz' ${VAR4@E}:'zzz' ${VAR4[@]@E}: 'zzz' var=VAR5 ${!var@E}:'' ${!var[@]@E}: '' ${VAR5@E}:'' ${VAR5[@]@E}: '' var=VAR6 ${!var@E}:'zzz' ${!var[@]@E}: 'zzz' ${VAR6@E}:'zzz' ${VAR6[@]@E}: 'zzz' var=VAR1 ${!var@P}:'' ${!var[@]@P}: '' ${VAR1@P}:'' ${VAR1[@]@P}: '' var=VAR2 ${!var@P}:'zzz' ${!var[@]@P}: 'zzz' ${VAR2@P}:'zzz' ${VAR2[@]@P}: 'zzz' var=VAR3 ${!var@P}:'' ${!var[@]@P}: '' ${VAR3@P}:'' ${VAR3[@]@P}: '' var=VAR4 ${!var@P}:'zzz' ${!var[@]@P}: 'zzz' ${VAR4@P}:'zzz' ${VAR4[@]@P}: 'zzz' var=VAR5 ${!var@P}:'' ${!var[@]@P}: '' ${VAR5@P}:'' ${VAR5[@]@P}: '' var=VAR6 ${!var@P}:'zzz' ${!var[@]@P}: 'zzz' ${VAR6@P}:'zzz' ${VAR6[@]@P}: 'zzz' var=VAR1 ${!var@A}:'' ${!var[@]@A}: '' ${VAR1@A}:'' ${VAR1[@]@A}: 'declare -rl VAR1=''' var=VAR2 ${!var@A}:'declare -rl VAR2='zzz'' ${!var[@]@A}: 'declare -rl VAR2='zzz'' ${VAR2@A}:'declare -rl VAR2='zzz'' ${VAR2[@]@A}: 'declare -rl VAR2='zzz'' var=VAR3 ${!var@A}:'' ${!var[@]@A}: '' ${VAR3@A}:'' ${VAR3[@]@A}: '' var=VAR4 ${!var@A}:'declare -arl VAR4='zzz'' ${!var[@]@A}: 'declare -arl VAR4='zzz'' ${VAR4@A}:'declare -arl VAR4='zzz'' ${VAR4[@]@A}: 'declare -arl VAR4=([0]="zzz")' var=VAR5 ${!var@A}:'' ${!var[@]@A}: '' ${VAR5@A}:'' ${VAR5[@]@A}: '' var=VAR6 ${!var@A}:'declare -Arl VAR6='zzz'' ${!var[@]@A}: 'declare -Arl VAR6='zzz'' ${VAR6@A}:'declare -Arl VAR6='zzz'' ${VAR6[@]@A}: 'declare -Arl VAR6=([0]="zzz" )' var=VAR1 ${!var@a}:'' ${!var[@]@a}: '' ${VAR1@a}:'rl' ${VAR1[@]@a}: 'rl' var=VAR2 ${!var@a}:'rl' ${!var[@]@a}: 'rl' ${VAR2@a}:'rl' ${VAR2[@]@a}: 'rl' var=VAR3 ${!var@a}:'' ${!var[@]@a}: '' ${VAR3@a}:'arl' ${VAR3[@]@a}: '' var=VAR4 ${!var@a}:'arl' ${!var[@]@a}: 'arl' ${VAR4@a}:'arl' ${VAR4[@]@a}: 'arl' var=VAR5 ${!var@a}:'' ${!var[@]@a}: '' ${VAR5@a}:'Arl' ${VAR5[@]@a}: '' var=VAR6 ${!var@a}:'Arl' ${!var[@]@a}: 'Arl' ${VAR6@a}:'Arl' ${VAR6[@]@a}: 'Arl' $ -- Arfrever Frehtes Taifersar Arahesis
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
> ${variable@A} does not work for scalar variables without values, but > interestingly ${variable[@]@A} works for them. More precisely, ${variable[@]@A} is non-empty, but not exactly correct. > See difference between ${VAR1@A} and ${VAR1[@]@A} below. ${VAR1[@]@A} is: declare -rl VAR1=''" But should be: declare -rl VAR1 As in output of 'declare -p VAR1'. -- Arfrever Frehtes Taifersar Arahesis
Unnecessary space in 'declare -p' and [@]@A for non-empty associative arrays
Notice unnecessary space before closing parenthesis for non-empty associative arrays (VAR5, VAR6) below: $ declare -a VAR1=() VAR2=(a) VAR3=(a b) $ declare -A VAR4=() VAR5=([0]=a) VAR6=([0]=a [1]=b) $ declare -p VAR{1,2,3,4,5,6} declare -a VAR1=() declare -a VAR2=([0]="a") declare -a VAR3=([0]="a" [1]="b") declare -A VAR4=() declare -A VAR5=([0]="a" ) declare -A VAR6=([1]="b" [0]="a" ) $ echo "${VAR1[@]@A}" declare -a VAR1=() $ echo "${VAR2[@]@A}" declare -a VAR2=([0]="a") $ echo "${VAR3[@]@A}" declare -a VAR3=([0]="a" [1]="b") $ echo "${VAR4[@]@A}" declare -A VAR4=() $ echo "${VAR5[@]@A}" declare -A VAR5=([0]="a" ) $ echo "${VAR6[@]@A}" declare -A VAR6=([1]="b" [0]="a" ) $ (BASH 5.0.16) -- Arfrever Frehtes Taifersar Arahesis
${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
${!variable@operator} does not work for variables without values. See empty values for all occurrences of ${!var@...} below. ${variable@A} does not work for scalar variables without values, but interestingly ${variable[@]@A} works for them. See difference between ${VAR1@A} and ${VAR1[@]@A} below. However neither ${variable@A} nor ${variable[@]@A} works for arrays without values. Both ${variable@a} and ${variable[@]@a} work for scalar variables without values. However ${variable[@]@a} does not work for arrays without values. See difference between ${VAR3@a} and ${VAR3[@]@a}, and between ${VAR5@a} and ${VAR5[@]@a} below. (BASH 5.0.16.) $ declare -lr VAR1 $ declare -lr VAR2=zzz $ declare -alr VAR3 $ declare -alr VAR4=(zzz) $ declare -Alr VAR5 $ declare -Alr VAR6=([0]=zzz) $ declare -p VAR{1,2,3,4,5,6} declare -rl VAR1 declare -rl VAR2="zzz" declare -arl VAR3 declare -arl VAR4=([0]="zzz") declare -Arl VAR5 declare -Arl VAR6=([0]="zzz" ) $ for operator in Q E P A a ; do for var in VAR{1,2,3,4,5,6} ; do echo "var=${var}" ; eval "echo \"\\\${!var@${operator}}: '\${!${var}@${operator}}'\"" ; eval "echo \"\\\${!var[@]@${operator}}: '\${!${var}[@]@${operator}}'\"" ; eval "echo \"\\\${${var}@${operator}}:'\${${var}@${operator}}'\"" ; eval "echo \"\\\${${var}[@]@${operator}}: '\${${var}[@]@${operator}}'\"" ; echo ; done ; done var=VAR1 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR1@Q}:'' ${VAR1[@]@Q}: '' var=VAR2 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR2@Q}:''zzz'' ${VAR2[@]@Q}: ''zzz'' var=VAR3 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR3@Q}:'' ${VAR3[@]@Q}: '' var=VAR4 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR4@Q}:''zzz'' ${VAR4[@]@Q}: ''zzz'' var=VAR5 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR5@Q}:'' ${VAR5[@]@Q}: '' var=VAR6 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR6@Q}:''zzz'' ${VAR6[@]@Q}: ''zzz'' var=VAR1 ${!var@E}:'' ${!var[@]@E}: '' ${VAR1@E}:'' ${VAR1[@]@E}: '' var=VAR2 ${!var@E}:'' ${!var[@]@E}: '' ${VAR2@E}:'zzz' ${VAR2[@]@E}: 'zzz' var=VAR3 ${!var@E}:'' ${!var[@]@E}: '' ${VAR3@E}:'' ${VAR3[@]@E}: '' var=VAR4 ${!var@E}:'' ${!var[@]@E}: '' ${VAR4@E}:'zzz' ${VAR4[@]@E}: 'zzz' var=VAR5 ${!var@E}:'' ${!var[@]@E}: '' ${VAR5@E}:'' ${VAR5[@]@E}: '' var=VAR6 ${!var@E}:'' ${!var[@]@E}: '' ${VAR6@E}:'zzz' ${VAR6[@]@E}: 'zzz' var=VAR1 ${!var@P}:'' ${!var[@]@P}: '' ${VAR1@P}:'' ${VAR1[@]@P}: '' var=VAR2 ${!var@P}:'' ${!var[@]@P}: '' ${VAR2@P}:'zzz' ${VAR2[@]@P}: 'zzz' var=VAR3 ${!var@P}:'' ${!var[@]@P}: '' ${VAR3@P}:'' ${VAR3[@]@P}: '' var=VAR4 ${!var@P}:'' ${!var[@]@P}: '' ${VAR4@P}:'zzz' ${VAR4[@]@P}: 'zzz' var=VAR5 ${!var@P}:'' ${!var[@]@P}: '' ${VAR5@P}:'' ${VAR5[@]@P}: '' var=VAR6 ${!var@P}:'' ${!var[@]@P}: '' ${VAR6@P}:'zzz' ${VAR6[@]@P}: 'zzz' var=VAR1 ${!var@A}:'' ${!var[@]@A}: '' ${VAR1@A}:'' ${VAR1[@]@A}: 'declare -rl VAR1=''' var=VAR2 ${!var@A}:'' ${!var[@]@A}: '' ${VAR2@A}:'declare -rl VAR2='zzz'' ${VAR2[@]@A}: 'declare -rl VAR2='zzz'' var=VAR3 ${!var@A}:'' ${!var[@]@A}: '' ${VAR3@A}:'' ${VAR3[@]@A}: '' var=VAR4 ${!var@A}:'' ${!var[@]@A}: '' ${VAR4@A}:'declare -arl VAR4='zzz'' ${VAR4[@]@A}: 'declare -arl VAR4=([0]="zzz")' var=VAR5 ${!var@A}:'' ${!var[@]@A}: '' ${VAR5@A}:'' ${VAR5[@]@A}: '' var=VAR6 ${!var@A}:'' ${!var[@]@A}: '' ${VAR6@A}:'declare -Arl VAR6='zzz'' ${VAR6[@]@A}: 'declare -Arl VAR6=([0]="zzz" )' var=VAR1 ${!var@a}:'' ${!var[@]@a}: '' ${VAR1@a}:'rl' ${VAR1[@]@a}: 'rl' var=VAR2 ${!var@a}:'' ${!var[@]@a}: '' ${VAR2@a}:'rl' ${VAR2[@]@a}: 'rl' var=VAR3 ${!var@a}:'' ${!var[@]@a}: '' ${VAR3@a}:'arl' ${VAR3[@]@a}: '' var=VAR4 ${!var@a}:'' ${!var[@]@a}: '' ${VAR4@a}:'arl' ${VAR4[@]@a}: 'arl' var=VAR5 ${!var@a}:'' ${!var[@]@a}: '' ${VAR5@a}:'Arl' ${VAR5[@]@a}: '' var=VAR6 ${!var@a}:'' ${!var[@]@a}: '' ${VAR6@a}:'Arl' ${VAR6[@]@a}: 'Arl' $ -- Arfrever Frehtes Taifersar Arahesis
Inconsistent termination of function when 'local' tries to override read-only variable
When scalar variable is read-only, then calling 'local' for this variable (regardless of presence of value in assignment) is non-fatal and subsequent commands in function are executed. When (indexed or associative) array is read-only, then calling 'local -a' or 'local -A' (without value) for this variable is non-fatal and subsequent commands in function are executed. Trying to set global variable without using 'local' is fatal. Trying to set global variable using 'local -g' is non-fatal. In other cases, function is terminated immediately. (BASH 5.0.16.) $ declare -r VAR1=a $ declare -ar VAR2=(a) $ declare -Ar VAR3=([a]=a) $ f() { local VAR1 VAR2 VAR3 ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local VAR1=b VAR2=b VAR3=b ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local -a VAR1 VAR2 VAR3 ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local -a VAR1=(b) ; echo AAA ; } ; f bash: f: VAR1: readonly variable $ f() { local -a VAR2=(b) ; echo AAA ; } ; f bash: f: VAR2: readonly variable $ f() { local -a VAR3=(b) ; echo AAA ; } ; f bash: f: VAR3: readonly variable $ f() { local -A VAR1 VAR2 VAR3 ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local -A VAR1=([b]=b) ; echo AAA ; } ; f bash: f: VAR1: readonly variable $ f() { local -A VAR2=([b]=b) ; echo AAA ; } ; f bash: f: VAR2: readonly variable $ f() { local -A VAR3=([b]=b) ; echo AAA ; } ; f bash: f: VAR3: readonly variable $ f() { local -g VAR1= VAR2= VAR3= ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { VAR1= ; echo AAA ; } ; f bash: VAR1: readonly variable $ f() { VAR2= ; echo AAA ; } ; f bash: VAR2: readonly variable $ f() { VAR3= ; echo AAA ; } ; f bash: VAR3: readonly variable $ -- Arfrever Frehtes Taifersar Arahesis
${variable@A} does not work for associative arrays
BASH 5.0.16. $ VAR1=aaa $ declare -a VAR2=(aaa) $ declare -A VAR3=([aaa]=aaa) $ declare -p VAR{1,2,3} declare -- VAR1="aaa" declare -a VAR2=([0]="aaa") declare -A VAR3=([aaa]="aaa" ) $ echo "${VAR1@A}" VAR1='aaa' $ echo "${VAR2@A}" declare -a VAR2='aaa' $ echo "${VAR3@A}" $ -- Arfrever Frehtes Taifersar Arahesis
Assignments to FUNCNAME break FUNCNAME
Manual of BASH claims: Assignments to FUNCNAME have no effect and return an error status. However assignments to FUNCNAME actually break FUNCNAME. I use BASH 4.3.30. Variant with local: $ A() { echo A; declare -p FUNCNAME; local FUNCNAME=(); } $ B() { echo B; declare -p FUNCNAME; } $ A A declare -a FUNCNAME='([0]=A)' bash: FUNCNAME: variable may not be assigned value $ A A declare -a FUNCNAME='([0]=A [1]=A)' bash: FUNCNAME: variable may not be assigned value $ A A declare -a FUNCNAME='([0]=A [1]=A [2]=A)' bash: FUNCNAME: variable may not be assigned value $ B B declare -a FUNCNAME='([0]=B [1]=A [2]=A [3]=A)' $ A A declare -a FUNCNAME='([0]=A [1]=A [2]=A [3]=A)' bash: FUNCNAME: variable may not be assigned value $ B B declare -a FUNCNAME='([0]=B [1]=A [2]=A [3]=A [4]=A)' $ Variant without local: $ A() { echo A; declare -p FUNCNAME; FUNCNAME=(); } $ B() { echo B; declare -p FUNCNAME; } $ A A declare -a FUNCNAME='([0]=A)' $ A A declare -a FUNCNAME='([0]=A [1]=A)' $ A A declare -a FUNCNAME='([0]=A [1]=A [2]=A)' $ B B declare -a FUNCNAME='([0]=B [1]=A [2]=A [3]=A)' $ A A declare -a FUNCNAME='([0]=A [1]=A [2]=A [3]=A)' $ B B declare -a FUNCNAME='([0]=B [1]=A [2]=A [3]=A [4]=A)' $ Also is it intentional that code after attempt of assignment to FUNCNAME is not run? The sentence in manual could be interpreted as simply setting $? to non-zero value and still running subsequent code. $ A() { echo A; local FUNCNAME=(); echo AAA; } $ A A bash: FUNCNAME: variable may not be assigned value $ -- Arfrever Frehtes Taifersar Arahesis signature.asc Description: This is a digitally signed message part.
Re: REGRESSION: shellshock patch rejects valid function names
2014-09-27 22:29 Eric Blake napisał(a): Thankfully, bash already forbids trying to name a function 'a=b' It works in bash 4.3.26: $ function a=b() { echo A; } $ a=b A $ a\=b A -- Arfrever Frehtes Taifersar Arahesis signature.asc Description: This is a digitally signed message part.
Re: REGRESSION: shellshock patch rejects valid function names
2014-09-27 23:12 Eric Blake napisał(a): On 09/27/2014 02:57 PM, Arfrever Frehtes Taifersar Arahesis wrote: 2014-09-27 22:29 Eric Blake napisał(a): Thankfully, bash already forbids trying to name a function 'a=b' It works in bash 4.3.26: $ function a=b() { echo A; } $ a=b A Oh, you used the 'function' keyword, coupled with NOT quoting the name of the function. I was trying to create the name via quotation: $ bash -c 'a\=b () { echo hi; }; a\=b' bash: `a\=b': not a valid identifier bash: a=b: command not found Still, since I strongly believe that import/export and valid function names should be the same set of characters, but that it would be extremely difficult to unambiguously encode = into environment variable function names, I think that we SHOULD take the step of forbidding '=' in function names (the 'function' keyword should NOT be able to define any function that cannot also be defined in isolation, nor which cannot be imported from the environment using whatever improved implementation we decide for function export/import). Ability to export/import functions with = in function names could be achieved by not embedding function names in environmental variables and using a single BASH_FUNCTIONS environmental variable whose value would contain code of all exported functions (in format similar to `declare -fpx` / `export -fp`). -- Arfrever Frehtes Taifersar Arahesis signature.asc Description: This is a digitally signed message part.
Re: 'local -x VARIABLE' does not clear variable for subprocesses
2014-05-05 17:18 Chet Ramey napisał(a): On 5/3/14, 7:22 PM, Arfrever Frehtes Taifersar Arahesis wrote: 'local -x VARIABLE' (without assignment of value) does not clear variable for subprocesses. It is regression in bash 4.3. It's not actually a regression; it's a bug fix. It's worth having the discussion again, though. A variable isn't set until it's assigned a value. A statement like `local x' or `export x' doesn't actually create a variable. It creates a `placeholder' so that a subsequent assignment will instantiate a variable with the right attributes, or change the behavior when a value is assigned, but does not assign a value itself. This means that something like export x echo ${x-unset} printenv x will display `unset'. The idea behind the bash-4.3 behavior is that the placeholder local variable isn't set, and doesn't really exist. It doesn't shadow a global variable with the same name until it gets a value. The bash-4.2 behavior was inconsistent: variables with attributes but without values weren't quite set (value == 0x0, but still visible) and weren't quite unset. Behavior of bash 4.3 is inconsistent between non-subshell subprocesses and other places: bash 4.2.47: $ export VAR{1,2}=abc $ f() { local VAR1; local -x VAR2; echo ### Normal scope:; declare -p VAR{1,2}; echo ### Subshell:; (declare -p VAR{1,2}); echo ### Non-subshell subprocess:; bash -c 'declare -p VAR{1,2}'; } $ f ### Normal scope: declare -x VAR1 declare -x VAR2 ### Subshell: declare -x VAR1 declare -x VAR2 ### Non-subshell subprocess: bash: line 0: declare: VAR1: not found bash: line 0: declare: VAR2: not found bash 4.3.11: $ export VAR{1,2}=abc $ f() { local VAR1; local -x VAR2; echo ### Normal scope:; declare -p VAR{1,2}; echo ### Subshell:; (declare -p VAR{1,2}); echo ### Non-subshell subprocess:; bash -c 'declare -p VAR{1,2}'; } $ f ### Normal scope: bash: declare: VAR1: not found bash: declare: VAR2: not found ### Subshell: bash: declare: VAR1: not found bash: declare: VAR2: not found ### Non-subshell subprocess: declare -x VAR1=abc declare -x VAR2=abc Ability to locally unset a variable also for subprocesses would be preferable solution. -- Arfrever Frehtes Taifersar Arahesis signature.asc Description: This is a digitally signed message part.
Re: 'local -x VARIABLE' does not clear variable for subprocesses
2014-05-05 22:12 Chet Ramey napisał(a): Ability to locally unset a variable also for subprocesses would be preferable solution. OK. I'm not sure exactly what this means. Can you give me an example? How would you use this in a situation where `unset' or `declare +x' are unusable? I would like to be able to unexport a variable for subprocesses called in given function, but not subprocesses called later outside of given function. Example of intended behavior (which happens to be behavior of bash 4.2): $ export VAR=abc $ f() { local -x VAR; bash -c 'declare -p VAR'; } $ f bash: line 0: declare: VAR: not found $ bash -c 'declare -p VAR' declare -x VAR=abc Bare 'unset' also unexports a variable for subprocesses called later outside of given function (both bash 4.2 and 4.3): $ export VAR=abc $ f() { unset VAR; bash -c 'declare -p VAR'; } $ f bash: line 0: declare: VAR: not found $ bash -c 'declare -p VAR' bash: line 0: declare: VAR: not found 'local' + 'unset' have effect on normal scope and subshells, but not on non-subshell subprocesses (both bash 4.2 and 4.3): bash 4.2: $ export VAR{1,2,3,4}=aaa $ f() { local VAR1 VAR2=bbb; local -x VAR3 VAR4=bbb; echo ## Before unsetting:; echo ### Normal scope:; declare -p VAR{1,2,3,4}; echo ### Subshell:; (declare -p VAR{1,2,3,4}); echo ### Non-subshell subprocess:; bash -c 'declare -p VAR{1,2,3,4}'; unset VAR{1,2,3,4}; echo ## After unsetting:; echo ### Normal scope:; declare -p VAR{1,2,3,4}; echo ### Subshell:; (declare -p VAR{1,2,3,4}); echo ### Non-subshell subprocess:; bash -c 'declare -p VAR{1,2,3,4}'; } $ f ## Before unsetting: ### Normal scope: declare -x VAR1 declare -x VAR2=bbb declare -x VAR3 declare -x VAR4=bbb ### Subshell: declare -x VAR1 declare -x VAR2=bbb declare -x VAR3 declare -x VAR4=bbb ### Non-subshell subprocess: bash: line 0: declare: VAR1: not found declare -x VAR2=bbb bash: line 0: declare: VAR3: not found declare -x VAR4=bbb ## After unsetting: ### Normal scope: bash: declare: VAR1: not found bash: declare: VAR2: not found bash: declare: VAR3: not found bash: declare: VAR4: not found ### Subshell: bash: declare: VAR1: not found bash: declare: VAR2: not found bash: declare: VAR3: not found bash: declare: VAR4: not found ### Non-subshell subprocess: declare -x VAR1=aaa declare -x VAR2=aaa declare -x VAR3=aaa declare -x VAR4=aaa $ bash -c 'declare -p VAR{1,2,3,4}' declare -x VAR1=aaa declare -x VAR2=aaa declare -x VAR3=aaa declare -x VAR4=aaa bash 4.3: $ export VAR{1,2,3,4}=aaa $ f() { local VAR1 VAR2=bbb; local -x VAR3 VAR4=bbb; echo ## Before unsetting:; echo ### Normal scope:; declare -p VAR{1,2,3,4}; echo ### Subshell:; (declare -p VAR{1,2,3,4}); echo ### Non-subshell subprocess:; bash -c 'declare -p VAR{1,2,3,4}'; unset VAR{1,2,3,4}; echo ## After unsetting:; echo ### Normal scope:; declare -p VAR{1,2,3,4}; echo ### Subshell:; (declare -p VAR{1,2,3,4}); echo ### Non-subshell subprocess:; bash -c 'declare -p VAR{1,2,3,4}'; } $ f ## Before unsetting: ### Normal scope: bash: declare: VAR1: not found declare -x VAR2=bbb bash: declare: VAR3: not found declare -x VAR4=bbb ### Subshell: bash: declare: VAR1: not found declare -x VAR2=bbb bash: declare: VAR3: not found declare -x VAR4=bbb ### Non-subshell subprocess: declare -x VAR1=aaa declare -x VAR2=bbb declare -x VAR3=aaa declare -x VAR4=bbb ## After unsetting: ### Normal scope: bash: declare: VAR1: not found bash: declare: VAR2: not found bash: declare: VAR3: not found bash: declare: VAR4: not found ### Subshell: bash: declare: VAR1: not found bash: declare: VAR2: not found bash: declare: VAR3: not found bash: declare: VAR4: not found ### Non-subshell subprocess: declare -x VAR1=aaa declare -x VAR2=aaa declare -x VAR3=aaa declare -x VAR4=aaa $ bash -c 'declare -p VAR{1,2,3,4}' declare -x VAR1=aaa declare -x VAR2=aaa declare -x VAR3=aaa declare -x VAR4=aaa 'declare +x' (or 'local +x') fails to unexport a variable when called in a function (both bash 4.2 and 4.3): $ export VAR=abc $ f() { declare +x VAR; bash -c 'declare -p VAR'; } $ f declare -x VAR=abc $ declare +x VAR $ bash -c 'declare -p VAR' bash: line 0: declare: VAR: not found -- Arfrever Frehtes Taifersar Arahesis signature.asc Description: This is a digitally signed message part.
'local -x VARIABLE' does not clear variable for subprocesses
'local -x VARIABLE' (without assignment of value) does not clear variable for subprocesses. It is regression in bash 4.3. Behavior of 'local VARIABLE' without -x option also changed, but I am not sure what should be correct behavior in that case. bash 4.2.47: $ export VAR1=abc VAR2=abc $ f() { local VAR1; local -x VAR2; bash -c 'declare -p VAR{1,2}'; } $ f bash: line 0: declare: VAR1: not found bash: line 0: declare: VAR2: not found bash 4.3.11: $ export VAR1=abc VAR2=abc $ f() { local VAR1; local -x VAR2; bash -c 'declare -p VAR{1,2}'; } $ f declare -x VAR1=abc declare -x VAR2=abc -- Arfrever Frehtes Taifersar Arahesis signature.asc Description: This is a digitally signed message part.
'declare +a -g' destroys local arrays
I use bash 4.2.45. `man bash` says: Using `+' instead of `-' turns off the attribute instead, with the exceptions that +a may not be used to destroy an array variable and +r will not remove the readonly attribute. However 'declare +a -g' destroys local arrays, which do not shadow global arrays: $ f() { local ARRAY=(a b c); declare -p ARRAY; declare +a -g ARRAY; declare -p ARRAY; } $ f declare -a ARRAY='([0]=a [1]=b [2]=c)' bash: declare: ARRAY: cannot destroy array variables in this way bash: declare: ARRAY: not found $ ARRAY=(x y z) $ f declare -a ARRAY='([0]=a [1]=b [2]=c)' bash: declare: ARRAY: cannot destroy array variables in this way declare -a ARRAY='([0]=a [1]=b [2]=c)' -- Arfrever Frehtes Taifersar Arahesis signature.asc Description: This is a digitally signed message part.
Subsequent `declare -fp` and `.` incorrectly restore function with here string with pattern substitution
Configuration Information: Machine: x86_64 OS: linux-gnu Compiler: x86_64-pc-linux-gnu-gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -DDEFAULT_PATH_VALUE='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' -DSTANDARD_UTILS_PATH='/bin:/usr/bin:/sbin:/usr/sbin' -DSYS_BASHRC='/etc/bash/bashrc' -DSYS_BASH_LOGOUT='/etc/bash/bash_logout' -DNON_INTERACTIVE_LOGIN_SHELLS -DSSH_SOURCE_BASHRC -march=core2 -O2 -pipe Machine Type: x86_64-pc-linux-gnu Bash Version: 4.0 Patch Level: 37 Release Status: release Description: Subsequent `declare -fp` and `.` incorrectly restore function with here string with pattern substitution. Repeat-By: The following function is incorrectly restored: here_string_test() { : ${var// /$'\n'} } Run the attached bash_test.sh script using this command: env -i bash_test.sh -- Arfrever Frehtes Taifersar Arahesis bash_test.sh Description: application/shellscript signature.asc Description: This is a digitally signed message part.