1

This answer about -- gives a lot of good information about using -- in POSIX shells and this answer about passing all arguments to a script led to the following function:

my_echo()
{
    set -x
    echo $@ " " \"$@\"
    echo `ps | grep -- "$@" | grep -v grep | awk '{ print $1 }'` 2>/dev/null
    set +x
}

my_echo logread -f

I'm writing this script for OpenWRT. The output from ash shows

+ echo logread -f   "logread -f"
logread -f   "logread -f"
+ ps
+ grep -v grep
+ awk { print $1 }
+ grep -- logread -f
grep: -f: No such file or directory
+ echo

+ set +x

Huh...the quotes I added to the grep command are gone (logread -f is left unquoted).

I tried this function in bash

+ echo logread -f ' ' '"logread' '-f"'
logread -f   "logread -f"
++ ps
++ grep --color=auto -- logread -f
++ grep --color=auto -v grep
++ awk '{ print $1 }'
grep: -f: No such file or directory
+ echo

+ set +x

Interesting...maybe my arguments are being parsed separately? To test this theory, I tried:

my_echo "logread -f"

Bash Output:

+ echo logread -f ' ' '"logread' '-f"'
logread -f   "logread -f"
++ ps
++ grep --color=auto -- 'logread -f'
++ grep --color=auto -v grep
++ awk '{ print $1 }'
+ echo

+ set +x

The output of the echo command didn't change (the set version or the actual output but logread -f now seems to be treated as if in double quotes. So...I got lucky because I misinterpreted set's translation of my commands. BUT, my function works now.

Ash Output:

+ echo logread -f   "logread -f"
logread -f   "logread -f"
+ ps
+ grep -v grep
+ awk { print $1 }
+ grep -- logread -f
+ echo

+ set +x

And now I'm getting what I expected. It turns out, running my_echo with arguments passed in double quotes (single argument) is the same as

my_echo_new()
{
    echo `ps | grep -- "$1" | grep -v grep | awk '{ print $1 }'` 2>/dev/null
}

my_echo_new "logread -f"

So...it sure seems like the issue is with working with multiple arguments. What is going on here? Is this a result of the ` or the result of the function call or something else? Why do I need double quotes in both places?

1 Answer 1

3

"$@" expands to a list of quoted strings. If you pass the two arguments logread and -f to your function, then "$@" would expand to two strings.

Running grep -- "$@" would therefore expand to grep -- logread -f, which means "grep for logread in the file called -f".

Would you want to pass separate arguments rather than a single string, then use "$*" to expand the arguments to a single quoted string.

grep -e "$*"

would expand to grep -e "logread -f". The positional parameters would be delimited by the first character in $IFS when using "$*" (by default, this is a space). Also note that using either $* or $@ unquoted does not make sense.

As an aside, I would probably opt for using pgrep/pkill here:

if ! pgrep -xf "$*" >/dev/null; then
    printf 'No process matches "%s" exactly\n' "$*"
fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .