In the answer below, I'm explicitly avoiding using grep
. A command line is a list of separate items, and it should be parsed as such, not as a line of text.
Assuming that you keep both the command and the arguments of the command in a single string (it would be better to use an array, see How can we run a command stored in a variable?), then you can do something like
process='cmd with "some arguments" and maybe name'
set -f
set -- $process
if [ "$1" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
shift
for arg do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
This would first disable filename generation, because we want to use $process
unquoted to split it up into separate words, and if that string contains filename globbing patterns (like *
), it would mess up our parsing of it. We do this with set -f
.
Then we set the positional parameters to the words in $process
. After that, if "$1"
is cmd
, we know we should be looking for name
in the rest of the command line. If not, we stop there.
We shift
off cmd
from the list of positional parameters and start looking at the arguments in a loop. In each iteration, we simply compare the argument to the string name
. If we find it, we say so and exit.
At the end of the loop, we know we haven't found the name
argument, so we report this and exit with a failure.
Note that in my example above, the argument some arguments
would be parsed as the two separate strings "some
and arguments"
, which is one of the reasons you'd never want to store a command and its arguments in a single string. It also means that it would detect the argument name
inside the single argument "some name string"
, which would be a false positive.
If the command line is stored in an array (in e.g. bash
), then you could do it like this:
process=( cmd with "some arguments" and maybe name )
if [ "${process[0]}" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
for arg in "${process[@]:1}"; do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
The expansion of "${process[@]:1}"
would be the whole array but not the first item (the command name).
For /bin/sh
(and dash
, but also bash
and any other POSIX shell), the above would be less wordy:
set -- cmd with "some arguments" and maybe name
if [ "$1" != 'cmd' ]; then
echo 'The command is not "cmd"'
exit 1
fi
shift
for arg do
if [ "$arg" = 'name' ]; then
echo 'Found "name" argument'
exit
fi
done
echo 'Did not find "name" argument in command line'
exit 1
This is essentially the same as the first piece of code, but with the correct handling of all the arguments (quoting etc.) since we never combine all the elements of the command line into a single text string.