4

I have this test variable in ZSH:

test_str='echo "a \" b c"'

I'd like to parse this into an array of two strings ("echo" "a \" b c").

i.e. Read test_str as the shell itself would and give me back an array of arguments.

Please note that I'm not looking to split on white space or anything like that. This is really about parsing arbitrarily complex strings into shell arguments.

2 Answers 2

9

Zsh has (z) modifier:

ARGS=( ${(z)test_str} )

. But this will produce echo and "a \" b c", it won’t unquote string. To unquote you have to use Q modifier:

ARGS=( ${(Q)${(z)test_str}} )

: results in having echo and a " b c in $ARGS array. Neither would execute code in or $(…), but (z) will split $(false true) into one argument.

that is to say:

% testfoo=${(z):-'blah $(false true)'}; echo $testfoo[2]
$(false true)
Sign up to request clarification or add additional context in comments.

3 Comments

(z) was the key. Thanks. I also added an example of what I think you meant with your last point.
I'm curious why you decided to use $(false true) as an example? Is it a convention or arbitrary / for the lack of a better command?
This is one of the few commands which have no side effects (except for the return code which may alter execution flow) and do not produce anything regardless of arguments (false in zsh is silent even in case false --help, it will not produce help like /bin/false --help from binutils does). Not a convention I know about, but using false or true commands with any arguments is safe, with the addition that specifically false command may fail a script depending on settings (like set -e).
5

A simpler (?) answer is hinted at by the wording of the question. To set shell argument, use set:

#!/bin/sh

test_str='echo "a \" b"'
eval set $test_str
for i; do echo $i; done

This sets $1 to echo and $2 to a " b. eval certainly has risks, but this is portable sh. It does not assign to an array, of course, but you can use $@ in the normal way.

1 Comment

Not sure if portable, but in bash, eval set - $test_str will prevent anything in $test_str being interpreted as the usual args to set

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.