[comp.unix.questions] Why doesn't this work?

jon@fdmetd.uucp (Jon Ivar Tr|stheim) (06/14/89)

Why does not the following command work in a Bourne shell script ?

	USERID=`expr "`id`" : 'uid=\([0-9]*\)(.*'`

The shell does not feed the whole argument list to 'expr(1)', so I get
the following error message:

	sh:   : 'uid=\([0-9]*\)(.*': execute permission denied

-- 
Jon Tr|stheim, Fellesdata a.s, P.O. Box 248, 0212 OSLO 2, NORWAY
Phone : +47 2 52 80 80                            Fax   : +47 2 52 85 10
E-mail : ...!mcvax!ndosl!fdmetd!jon  or           jon@fdmetd.uucp
<The opinions expressed, if any, do not represent Fellesdata a.s>

maart@cs.vu.nl (Maarten Litmaath) (06/15/89)

jon@fdmetd.uucp (Jon Ivar Tr|stheim) writes:
\Why does not the following command work in a Bourne shell script ?
\
\	USERID=`expr "`id`" : 'uid=\([0-9]*\)(.*'`
               ^      ^  ^                       ^
	       |      |  |                       |
	       +------+  +-----------------------+

1) As shown above, sh doesn't parse the expression the way you intended.
   I consider this a bug.
   Anyhow another bug is revealed: the first command between backquotes
   doesn't generate an error message.
2) The output of `id' is something like:

	uid=0(root) gid=0(wheel)
	           ^
		   This space splits the output into TWO words,
		   which `expr' isn't too happy with.
Solution:

	USERID=`expr "\`id\`" : 'uid=\([0-9]*\)(.*'`
-- 
"I HATE arbitrary limits, especially when |Maarten Litmaath @ VU Amsterdam:
   they're small."  (Stephen Savitzky)    |maart@cs.vu.nl, mcvax!botter!maart

leo@philmds.UUCP (Leo de Wit) (06/15/89)

In article <2761@piraat.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
|jon@fdmetd.uucp (Jon Ivar Tr|stheim) writes:
|\Why does not the following command work in a Bourne shell script ?
|\
|\	USERID=`expr "`id`" : 'uid=\([0-9]*\)(.*'`
|               ^      ^  ^                       ^
|	       |      |  |                       |
|	       +------+  +-----------------------+
|
|1) As shown above, sh doesn't parse the expression the way you intended.
|   I consider this a bug.

This is definitely NOT a bug, but the way shell quoting is documented
to behave. From S.R.Bourne, 'An Introduction to the UNIX Shell':

The following table gives, for each quoting mechanism, the shell
metacharacters that are evaluated.

					metacharacter
		\	$	*	`	"	'
	'	n	n	n	n	n	t
	`	y	n	n	t	n	n
	"	y	y	n	y	t	n

		t	terminator
		y	interpreted
		n	not interpreted

(end of quote 8-)
So, between `` the " metacharacter is to be taken literal (it is
of course interpreted in the forked shell).

|   Anyhow another bug is revealed: the first command between backquotes
|   doesn't generate an error message.

Strictly speaking you are correct; for some reason sh accepts
end-of-file as terminator of (any?) quoting. The following script that
has a comparable error, doesn't draw an error message either:

------ start of script ------
#! /bin/sh

echo "
Where does it all end ...
------ end of script ------

    Leo.

rikki@macom1.UUCP (R. L. Welsh) (06/16/89)

From article <443@fdmetd.uucp>, by jon@fdmetd.uucp (Jon Ivar Tr|stheim):
> Why does not the following command work in a Bourne shell script ?
> 	USERID=`expr "`id`" : 'uid=\([0-9]*\)(.*'`

Try doing:
 	USERID=`expr "\`id\`" : 'uid=\([0-9]*\)(.*'`


Because ` will still work inside ".
-- 
	- Rikki	(UUCP: grebyn!macom1!rikki)

dg@lakart.UUCP (David Goodenough) (07/22/89)

jon@fdmetd.uucp (Jon Ivar Tr|stheim) sez:
> Why does not the following command work in a Bourne shell script ?
> 
> 	USERID=`expr "`id`" : 'uid=\([0-9]*\)(.*'`
> 
> The shell does not feed the whole argument list to 'expr(1)', so I get
> the following error message:
> 
> 	sh:   : 'uid=\([0-9]*\)(.*': execute permission denied

Possibly because `` constructs don't nest, at least not any way I've tried.

Try this:

STUG=`id`
USERID=`expr "$STUG" : 'uid=\([0-9]*\)(.*'`
-- 
	dg@lakart.UUCP - David Goodenough		+---+
						IHS	| +-+-+
	....... !harvard!xait!lakart!dg			+-+-+ |
AKA:	dg%lakart.uucp@xait.xerox.com		  	  +---+

dmt@PacBell.COM (Dave Turner) (08/02/89)

In article <579@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes:
.jon@fdmetd.uucp (Jon Ivar Tr|stheim) sez:
.> Why does not the following command work in a Bourne shell script ?
.> 
.> 	USERID=`expr "`id`" : 'uid=\([0-9]*\)(.*'`
.Possibly because `` constructs don't nest, at least not any way I've tried.
.
.Try this:
.
.STUG=`id`
.USERID=`expr "$STUG" : 'uid=\([0-9]*\)(.*'`

Or escape the inner backquotes:

	USERID=`expr "\`id\`" : 'uid=\([0-9]*\)(.*'`

This works on the Bourne and Korn shells using System V R2.1 on a 3B20.


-- 
Dave Turner	415/542-1299	{att,bellcore,sun,ames,decwrl}!pacbell!dmt

frank@zen.co.uk (Frank Wales) (08/04/89)

In article <4900@ptsfa.PacBell.COM> dmt@PacBell.COM (Dave Turner) writes:
>jon@fdmetd.uucp (Jon Ivar Tr|stheim) sez:
>> Why does not the following command work in a Bourne shell script ?
>> 	USERID=`expr "`id`" : 'uid=\([0-9]*\)(.*'`
>
>escape the inner backquotes:
>
>	USERID=`expr "\`id\`" : 'uid=\([0-9]*\)(.*'`
>
>This works on the Bourne and Korn shells using System V R2.1 on a 3B20.

On Korn shell only, you can also use the form $(command) instead of
`command`, which nests and is more readable for complicated
command substitutions.
--
Frank Wales, Systems Manager,        [frank@zen.co.uk<->mcvax!zen.co.uk!frank]
Zengrange Ltd., Greenfield Rd., Leeds, ENGLAND, LS9 8DB. (+44) 532 489048 x217 

hallt@handel.CS.ColoState.Edu (Tim C. Hall) (06/25/91)

Hi all,
   I want to write a single command that will perform some action on
every host that shows as "up" in the output of ruptime.  So far I have:

ruptime | grep up | awk '{ print $1 }' | xargs -i -t remsh {} cat /log

Using the -t option of xargs, it echoes the first command formed by 
the first "up" host listed in the ruptime, then runs that command.  
However, it drops me back into the shell after executing with only
the first host, it doesn't substitute the remainder of the hosts
coming through the pipe.  Why?  Running this command without the
xargs portion yields a list of all our "up" hosts, delimited by a
carriage return.  What am I missing here?  Please email all responses,
I'll post a summary to the net if there is sufficient interest.  Oh yeah,
we're running System V 3.2.2 on an ATT 3B2/600.

Thanks in advance.

Tim C. Hall
hallt@handel.cs.colostate.edu

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (07/01/91)

In article <15679@ccncsu.ColoState.EDU>, hallt@handel.CS.ColoState.Edu (Tim C. Hall) writes:

> ruptime | grep up | awk '{ print $1 }' | xargs -i -t remsh {} cat /log

> Using the -t option of xargs, it echoes the first command formed by
> the first "up" host listed in the ruptime, then runs that command.
> However, it drops me back into the shell after executing with only
> the first host, it doesn't substitute the remainder of the hosts
> coming through the pipe.  Why?

Good question.

> Running this command without the xargs portion yields a list of all
> our "up" hosts, delimited by a carriage return.

More likely a newline....

The most probable thing that comes to mind is that the remsh command
being run by xargs inhereits xargs' stdin.  And on the assumption that
remsh is something like the Berkeley rsh, it doesn't realize that cat
isn't interested in reading input, so it copies from its stdin to cat's
stdin.  Then cat dies, remsh exits, and the other hostnames get dropped
when the pipe's buffer is thrown away ('cause cat never read it).

If remsh has an option like rsh's -n option, to effectively redirect
stdin from /dev/null, use that.  If xargs runs a shell to execute the
command, you may be able to do

	.... | xargs -i -t remsh {} cat /log \< /dev/null

Based on an experiment with sh here, you may also be able to do

	.... | xargs -i -t sh -c 'remsh $0 cat /log </dev/null' {}

or something similar.

If none of those work, you may have to write a script file, something
like

	% cat catlog
	remsh $1 cat /log < /dev/null

and then

	.... | xargs -i -t catlog {}

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu