3

Is there a way in Bash (without calling a 2nd script) to parse variables as if they were command line arguments? I'd like to be able to group them by quotes and such.

Example:

this="'hi there' name here"

for argument in $this; do
    echo "$argument"
done

which should print (but obviously doesn't)

hi there
name
here
1

3 Answers 3

3

Don't store the arguments in a string. Arrays were invented for this purpose:

this=('hi there' name here)

for argument in "${this[@]}"; do
    echo "$argument"
done

It is highly recommended that you use this approach if you have control over this. If you don't, that is even more reason not to use eval, since unintended commands can be embedded in the value of this. For example:

$ this="'hi there'); echo gotcha; foo=("
$ eval args=($this)
gotcha

Less nefarious is something as simple as this="'hi there' *". eval will expand the * as a pattern, matching every file in the current directory.

Sign up to request clarification or add additional context in comments.

1 Comment

I'm getting input from a read prompt or a Zenity dialog. Is there any way to get it into an array from that?
2

I worked out a half-answer myself. Consider the following code:

this="'hi there' name here"

eval args=($this)

for arg in "${args[@]}"; do
    echo "$arg"
done

which prints the desired output of

hi there
name
here

Comments

1

Using gsed -r:

echo "$this" | gsed -r 's/("[^"]*"|[^" ]*) */\1\n/g'
"hi there"
name
here

Using egrep -o:

echo "$this" | egrep -o '"[^"]*"|[^" ]+'
"hi there"
name
here

Pure BASH way:

this="'hi there' name here"
s="$this"
while [[ "$s" =~ \"[^\"]*\"|[^\"\ ]+ ]]; do
    echo ${BASH_REMATCH[0]}
    l=$((${#BASH_REMATCH[0]}+1))
    s="${s:$l}"
done

"hi there"
name
here

Comments

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.