Date: Sun, 26 Dec 1999 22:08:48 +0100 (CET) From: Oliver Fromme <olli@dorifer.heim3.tu-clausthal.de> To: freebsd-questions@FreeBSD.ORG Subject: Re: shell quoting problem? Message-ID: <199912262108.WAA12707@dorifer.heim3.tu-clausthal.de>
next in thread | raw e-mail | index | archive | help
aunty@comcen.com.au wrote in list.freebsd-questions:
> After setting some variables in a bourne shell script, I want it
> to run a command like
> finger @nas1 | egrep "Host|tom|dick|harry"
> where nas1, tom, dick, and harry are expanded from variables.
>
> I can see _why_ things like this don't work
> finger \@${serv} | egrep \"Host${pipes-and-names}\"
> but can't figure out how to get all those quotes and pipes behaving.
You don't have to escape the "at" sign or the doublequotes.
Something like this works fine as a shell script:
#!/bin/sh -
serv=nas1
pipes_and_names="|tom|dick|harry"
finger @${serv} | egrep "Host${pipes_and_names}"
The braces are not necessary in this case, because it is clear
where the variable names end. Braces around them are only
required when the names are followed by characters that might
belong to the variable reference (letters, digits, underscore),
or when one of the expansion modifiers is used (for example
${foo:-bar} to insert a default value). Of course, the braces
never hurt. You can always use them, just to be safe.
In fact, in this case the doublequotes in the egrep command are
not necessary either (but they don't hurt either), because the
argument does not contain any whitespace.
Shell quoting can be a bit tricky if you're not familiar with
it. Single quotes can be used to escape the special meaning of
_all_ characters, except single quotes themselves (obviously).
This means that variable names in single quotes ('$foo') are
not expanded.
Double quotes escape everything _except_ double quotes, dollar
signs (for variable expansion), backslashes and backticks (`)
(for command substitution). Inside double quotes, backslashes
can be used to escape the special meaning of those characters.
Outside of quotes, backslashes can be used to escape all
special characters.
It is important to know that the shell expands variables first,
and _then_ it performs whitespace splitting (tokenizing). That
means that you have to use double quotes if you want to use a
variable within a single argument that might contain whitespace
(spaces, tabs, newlines):
VAR="foo bar"
... | grep $VAR --> grep foo bar
... | grep "$VAR" --> grep "foo bar"
... | grep '$VAR' --> grep '$VAR'
When you escape the doublequotes with backslashes like this:
egrep \"$VAR\"
then the double quotes will lose their special meaning and will
be given to the egrep command as-is. Thus, the string itself
is not quoted, so this also means that whitespace splitting
_will_ happen on the string (after expanding any variables).
I.e. if $VAR is defined as above, then the first argument to
egrep will be
"foo
and the second argument will be
bar"
including the doublequotes. This would make egrep search for a
file called ``bar"'' and find all occurences of ``"foo'' in it.
This is probably not what you want.
> Is there a way to do this or must I resort to perl?
There's certainly no reason to use perl. In perl, quoting can
be even more difficult. :-)
The bourne shell only has few rules for quoting and variable
expansion. Once you know how they interact with each other,
it's not that difficult anymore.
Regards
Oliver
--
Oliver Fromme, Leibnizstr. 18/61, 38678 Clausthal, Germany
(Info: finger userinfo:olli@dorifer.heim3.tu-clausthal.de)
"In jedem Stück Kohle wartet ein Diamant auf seine Geburt"
(Terry Pratchett)
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199912262108.WAA12707>
