2

On https://www.virtuability.com/public/wp/?p=12 I saw this notation:

oarr=($output)

export AWS_ACCESS_KEY_ID="${oarr[1]}"
export AWS_SECRET_ACCESS_KEY="${oarr[3]}"
export AWS_SESSION_TOKEN="${oarr[4]}"

Which shell allows oarr=($output)?

Output would be like this:

CREDENTIALS EUROIWPPEACEGPNASIA 2017-03-19T23:09:47Z z66Pku1EFb6dCP1+02RWzRhaYEGPpLy6xcjZz3rr FqODYXdzEMT//////////wEaDNYYo0b6nFVNB2mLsCKvAW2+69FQoDlxLFeBYfznVdS67QPGfFiRvMDd4f5VxkHosv2oFtXAHu8IedzzXT/Ex2P2Gce6Y2b8yBwzylaZAAu53SW9pesjunVprkzNVA3IznRj4hlTTgx8DTos4n+qDEfElv5lEvYKaNg2ER7/BtXTdzAwTNu1QHiMvNVySHnvZHgW5G5oHBEnYgsyR1guxyP/8hiRyR3nuUE0BMIl5+LVBaYaP637HlAXHQ+83KUo+5Ya1QU=

With /bin/sh and /bin/bash I only get empty ${oarr[1]} ${oarr[3]} ${oarr[4]}

codeforester
  • 39,467
  • 16
  • 112
  • 140
chriscatfr
  • 2,592
  • 3
  • 24
  • 32
  • 3
    It's bash, but it's *buggy* bash. Doing it right would be more like `IFS=$' \t' read -r -a oarrr <<<"$output"` – Charles Duffy Mar 19 '18 at 19:54
  • 1
    ...that said, the bug in question isn't triggered in the use case here (unless `IFS` is previously set to a non-default value) -- so, if you say the values are empty, you'll need to demonstrate that with code we can copy, paste and run ourselves to see that result. See https://ideone.com/vq9fLK for an online interpreter running your code in bash -- and showing the variables not at all being empty. – Charles Duffy Mar 19 '18 at 19:56
  • 1
    ...my own informed guess here is that you're doing something like `IFS=$'\n'` up at the top of your script, which changes the behavior of unquoted expansions, and thereby triggers a bug in the code you're trying to use. – Charles Duffy Mar 19 '18 at 20:09
  • 2
    @codeforester, ...I think your title substantially changes the meaning of the question. The OP is trying to figure out for which shell the code in question populates an array, because they think it doesn't work in bash -- presumably due to a faulty test procedure (such as having injected it into a larger script with a non-default `IFS`, causing all the content to go into `oarr[0]`). – Charles Duffy Mar 19 '18 at 20:18
  • @CharlesDuffy, I just rolled it back. – codeforester Mar 19 '18 at 20:19
  • 1
    thanks guys. Once I was sure it was BASH i could focus on the issue. And thanks to this change in title I got good advice on that. – chriscatfr Mar 20 '18 at 11:02

1 Answers1

4

That's an array assignment in Bash. The words from the expansion of $output become array elements, starting with index 0.

For example:

string="one two three"
arr=($string)   # Bash does word splitting (see doc links below)
                # and globbing (wildcards '*', '?' and '[]' will be expanded to matching filenames)

declare -p arr  # gives declare -a arr='([0]="one" [1]="two" [2]="three")'
arr=("$string") # Word splitting is suppressed because of the quotes - but this won't be useful because the entire string ends up as the first element of the array
declare -p arr  # gives declare -a arr='([0]="one two three")'

To prevent word splitting and globbing, the right way to convert your space delimited string to an array is:

read -r -a oarr <<< "$output"

Run declare -p oarr to verify the content of your array. That will tell you why ${oarr[1]} ${oarr[3]} ${oarr[4]} are empty in your current code.


If you have a different delimiter, say :, then:

IFS=: read -r -a arr <<< "$string"

See:

codeforester
  • 39,467
  • 16
  • 112
  • 140
  • 1
    This is true, but it's probably worth pointing out why the OP's code is buggy and what the best-practice alternative is. – Charles Duffy Mar 19 '18 at 19:55
  • 2
    (If there's a `*` in their data, they probably don't want it replaced with a list of filenames, which `arr=($string)` will do). – Charles Duffy Mar 19 '18 at 19:58
  • 1
    `arr=("$output")` is just *useless*. You might as well just keep your data in a single string rather than transposing it to a single-element array. Presumably they do actually want string-splitting; that they want globbing... much less likely. – Charles Duffy Mar 19 '18 at 19:59
  • 1
    Also, because the other items are empty, it's overwhelmingly likely that `IFS` was set to a non-default value elsewhere in their script, hence the string-splitting they expect not taking place. If you use `read -a`, you can set a new `IFS` value scoped to that one command without impacting code anywhere else. – Charles Duffy Mar 19 '18 at 20:00
  • 1
    ...so, if they *do* in fact have a non-default `IFS`, you'll want to specify one that's appropriate to their data when invoking `read`. (And if they didn't, I can't really see how they would have ended up asking this question at all, as the non-`0` elements wouldn't be empty). – Charles Duffy Mar 19 '18 at 20:01
  • 1
    ...to be clear, they're showing that the real separator in their data is whitespace. So that `oarr[1]` is empty (as the question says it is) means that in a different part of their real code *where they aren't showing us* they set `IFS` to a non-default value -- or else the bug they asked the question about wouldn't happen at all. So the need is not to set `IFS=:` but rather `IFS=' '`, so `read -a` still works even if up at the top of their script they did something silly like `IFS=$'\n'`. – Charles Duffy Mar 19 '18 at 20:06