From owner-freebsd-questions Sun Dec 26 13: 8:53 1999 Delivered-To: freebsd-questions@freebsd.org Received: from dorifer.heim3.tu-clausthal.de (dorifer.heim3.tu-clausthal.de [139.174.243.252]) by hub.freebsd.org (Postfix) with ESMTP id CE90D14FBE for ; Sun, 26 Dec 1999 13:08:49 -0800 (PST) (envelope-from olli@dorifer.heim3.tu-clausthal.de) Received: (from olli@localhost) by dorifer.heim3.tu-clausthal.de (8.8.8/8.8.8) id WAA12707 for freebsd-questions@FreeBSD.ORG; Sun, 26 Dec 1999 22:08:48 +0100 (CET) (envelope-from olli) Date: Sun, 26 Dec 1999 22:08:48 +0100 (CET) From: Oliver Fromme Message-Id: <199912262108.WAA12707@dorifer.heim3.tu-clausthal.de> To: freebsd-questions@FreeBSD.ORG Subject: Re: shell quoting problem? Organization: Administration TU Clausthal Reply-To: freebsd-questions@FreeBSD.ORG MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-Newsreader: TIN [version 1.2 RZTUC(3) PL2] Sender: owner-freebsd-questions@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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