2

I want to construct array element with space, it works while run in command line:

pc:/tmp$ b=('1 2' '3 4')
pc:/tmp$ echo $b
1 2
pc:/tmp$ echo ${b[1]}
3 4

But it get the elements split with space in script:

pc:/tmp$ cat t.sh
a="'1 2' '3 4'"
echo $a
b=($a)
echo $b
echo ${b[1]}
echo ${b[2]}

pc:/tmp$ bash t.sh
'1 2' '3 4'
'1
2'
'3

I want to get '1 2' with echo $b as get '3 4' with ${b[1]} in script.

How could I achieve this?

And why it can't not works in script but works in command line?

Victor Lee
  • 2,467
  • 3
  • 19
  • 37
  • 3
    `b=($a)` splits the string on white space. You would have to write a parser for your `a` to tear it apart. – user1934428 Sep 27 '21 at 14:19
  • If you tested `b=($a)` at the command line it would behave just the same way as it did in your script. This isn't a script-vs-command-line difference. – Charles Duffy Sep 27 '21 at 15:32
  • BTW, among the answers on the duplicates, I strongly suggest finding one that uses either the Python `shlex` module (if you want the closest possible accuracy to a real POSIX sh parser), or `xargs printf '%s\0'` (if you want something that's available everywhere and doesn't add more bugs than the minimum set `xargs` forces). – Charles Duffy Sep 27 '21 at 15:35
  • @CharlesDuffy THX, thanks for your time, maybe I should improve my search skill, that all relevant questions are helpful. – Victor Lee Sep 27 '21 at 16:18

1 Answers1

4

The code a="'1 2' '3 4'" does not create an array, it creates a string with embedded single-quotes.

$: a="'1 2' '3 4'"
$: echo "[$a]"
['1 2' '3 4']

If you want to create an array, you have to use the right syntax.

$: a=( '1 2' '3 4' )
$: printf "[%s]\n" "${a[@]}"
[1 2]
[3 4]

Then if you want to copy it to another array, just treat it like an array instead of a string.

b=( "${a[@]}" )
printf "[%s]\n" "${b[@]}"
[1 2]
[3 4]

To convert the string created in a="'1 2' '3 4'" to an array is a little trickier.

IF you know that the format is a consistent match for the above, try this:

$: echo "[$a]"
['1 2' '3 4']
$: IFS='#' read -ra b < <( sed -E "s/' +'/#/g; s/ *' *//g" <<< "$a" )
$: printf "[%s]\n" "${b[@]}"
[1 2]
[3 4]

but generally, this is a bad plan. Try to fix your input!

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36