jbayer@ispi.UUCP (Jonathan Bayer) (09/16/89)
HELP!! I have been pulling my hair out over this seemingly simple problem: I have to get the user id, and then get the user description from /etc/passwd. Now, getting the user id was easy. The script is below: LOGNAME=`who am i | awk '{ logname=$1 print logname }'` LOGNAME is set nicely here. However, when I try to do something similar to /etc/passwd as follows: a=" awk -F: '\$1 == \"$LOGNAME\" { user=\$5; print user }'" USER=`cat /etc/passwd | $a` I get the following error: awk: syntax error at source line 1 context is >>> ' <<< awk: bailing out at source line 1 Now, the following line does work (when I hardcode in LOGNAME): USER=`cat /etc/passwd | awk -F: '$1 == "root" { user=$5; print user }'` So my question is, what am I doing wrong here? I am not that fluent in awk, so this doesn't make too much sense right now. This is running on an SCO Xenix 386, 2.3.3 system. JB -- Jonathan Bayer Intelligent Software Products, Inc. (201) 245-5922 500 Oakwood Ave. jbayer@ispi.COM Roselle Park, NJ 07204
karish@forel.stanford.edu (Chuck Karish) (09/17/89)
In article <1163@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) wrote:
<LOGNAME=`who am i | awk '{
< logname=$1
< print logname
< }'`
<
<a=" awk -F: '\$1 == \"$LOGNAME\" {
< user=\$5;
< print user
< }'"
<USER=`cat /etc/passwd | $a`
USER=`cat /etc/passwd | eval $a`
Chuck Karish karish@mindcraft.com
(415) 493-9000 karish@forel.stanford.edu
hinton@netcom.UUCP (Greg Hinton) (09/18/89)
In article <1163@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes: > [ . . . . ] >I have to get the user id, and then get the user description from /etc/passwd. > [ . . . . ] How about this: grep \^`who am i | cut -d' ' -f1`\: /etc/passwd | cut -d: -f5 -- Greg Hinton DOMAIN: hinton@netcom.uucp UUCP: uunet!apple!netcom!hinton
ok@cs.mu.oz.au (Richard O'Keefe) (09/18/89)
In article <2412@netcom.UUCP>, hinton@netcom.UUCP (Greg Hinton) writes: : In article <1163@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes: : >I have to get the user id, and then get the user description from /etc/passwd. : How about this: : grep \^`who am i | cut -d' ' -f1`\: /etc/passwd | cut -d: -f5 Watch out for BSD-derived systems, where the first "word" from the "who am i" command has the form "machine!user", e.g. munmurra!ok. You want the bit after the !. A much simpler method is to use a shell variable. Check "environ" in the manual, and you'll find that you have LOGNAME # System V or USER # BSD or both. Just do grep "^${LOGNAME}:" /etc/passwd | what-ever-you-want-here Again, watch out for Yellow Pages; if you're using that you have to do ypcat passwd | grep "^${LOGNAME}" | what-ever-you-want-here
guy@auspex.auspex.com (Guy Harris) (09/20/89)
>>: >I have to get the user id, and then get the user description from >>: >/etc/passwd. >>Again, watch out for Yellow Pages; if you're using that you have to do... Or, if you want to do something that's independent of the details of how password file access is implemented, try the attached commands. "getpwnam" takes one argument, a user name, and prints its password file entry; "getpwuid" takes one argument, a user ID number, and prints its password file entry. This should work fine, and use the most efficient access form available, if you have: a traditional text file "/etc/passwd"; a "dbm" database, 4.3BSD-style; a Yellow Pages map, or some other network server-based map (e.g., Hesiod, if the "optional" implementations of "getpwnam()" and its "inverse counterpart" are present; does the Apollo Registry implementation have "getpwnam()" and "getpwuid()" routines that query the registry?); or anything else that has "getpwnam()" and "getpwuid()" routines. and if your system actually implements the most efficient access form available in "getpwnam()" and "getpwuid()". With any luck, these should run on anything V7 or later. If you have something later, you can consider other improvements, such as using "strtol" instead of "atoi" to convert the user ID, and catch non-numeric strings, if your system has "strtol". #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: getpwnam.c getpwuid.c # Wrapped by guy@auspex on Tue Sep 19 11:28:42 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'getpwnam.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getpwnam.c'\" else echo shar: Extracting \"'getpwnam.c'\" \(523 characters\) sed "s/^X//" >'getpwnam.c' <<'END_OF_FILE' X#include <stdio.h> X X#include <pwd.h> X Xextern struct passwd *getpwnam(); X Xint Xmain(argc, argv) X int argc; X char **argv; X{ X register struct passwd *pw; X X if (argc != 2) { X fprintf(stderr, "Usage: getpwnam <username>\n"); X exit(1); X } X if ((pw = getpwnam(argv[1])) == NULL) { X fprintf(stderr, "getpwnam: No such user \"%s\"\n", X argv[1]); X exit(2); X } X printf("%s:%s:%d:%d:%s:%s:%s\n", X pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, X pw->pw_gecos, pw->pw_dir, pw->pw_shell); X exit(0); X /*NOTREACHED*/ X} END_OF_FILE if test 523 -ne `wc -c <'getpwnam.c'`; then echo shar: \"'getpwnam.c'\" unpacked with wrong size! fi # end of 'getpwnam.c' fi if test -f 'getpwuid.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getpwuid.c'\" else echo shar: Extracting \"'getpwuid.c'\" \(528 characters\) sed "s/^X//" >'getpwuid.c' <<'END_OF_FILE' X#include <stdio.h> X X#include <pwd.h> X Xextern struct passwd *getpwuid(); X Xint Xmain(argc, argv) X int argc; X char **argv; X{ X register struct passwd *pw; X X if (argc != 2) { X fprintf(stderr, "Usage: getpwuid <user id>\n"); X exit(1); X } X if ((pw = getpwuid(atoi(argv[1]))) == NULL) { X fprintf(stderr, "getpwuid: No such user \"%s\"\n", X argv[1]); X exit(2); X } X printf("%s:%s:%d:%d:%s:%s:%s\n", X pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, X pw->pw_gecos, pw->pw_dir, pw->pw_shell); X exit(0); X /*NOTREACHED*/ X} END_OF_FILE if test 528 -ne `wc -c <'getpwuid.c'`; then echo shar: \"'getpwuid.c'\" unpacked with wrong size! fi # end of 'getpwuid.c' fi echo shar: End of shell archive. exit 0
bob@omni.com (Bob Weissman) (09/20/89)
In article <2130@munnari.oz.au>, ok@cs.mu.oz.au (Richard O'Keefe) writes: > Again, watch out for Yellow Pages; if you're using that you have to do > ypcat passwd | grep "^${LOGNAME}" | what-ever-you-want-here I hate to see this kind of inefficiency advertised. Use ypmatch $LOGNAME passwd | whatever instead. -- Bob Weissman <bob@omni.com> UUCP: ...!{apple,pyramid,sgi,tekbspa,uunet}!koosh!bob Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
wesommer@athena.mit.edu (William Sommerfeld) (09/20/89)
In article <2471@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
Does the Apollo Registry implementation have "getpwnam()" and "getpwuid()"
routines that query the registry?
Yes, it does.
--
gs26@prism.gatech.EDU (Glenn R. Stone) (09/20/89)
In article <2130@munnari.oz.au> ok@cs.mu.oz.au (Richard O'Keefe) writes: >In article <2412@netcom.UUCP>, hinton@netcom.UUCP (Greg Hinton) writes: >: In article <1163@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes: >: >I have to get the user id, and then get the user description from >: >/etc/passwd. >Again, watch out for Yellow Pages; if you're using that you have to do > ypcat passwd | grep "^${LOGNAME}" | what-ever-you-want-here Ummm.... I don't think this is the preferred method, especially when yp is dbm-ized... you REALLY don't want do do this if you have a yp like this one, with yppasswd something on the order of the lower half of five figures left of the decimal. Better is ypmatch $LOGNAME passwd | yourprog which lets yp do what it's supposed to, namely, look up a passwd entry quickly and efficiently, no muss, no fuss, you'll be home in time for dinner. Glenn R. Stone gs26@prism.gatech.edu, CCASTGS@GITNVE2.BITNET, ...!gatech!gitpyr!ccastgs Box 30372, Atlanta, GA 30332 "We know it's impossible, now how's the best way to do it?"
clewis@eci386.uucp (Chris Lewis) (09/21/89)
In article <1163@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes: > >HELP!! I have been pulling my hair out over this seemingly simple >problem: >a=" awk -F: '\$1 == \"$LOGNAME\" { > user=\$5; > print user > }'" >USER=`cat /etc/passwd | $a` >I get the following error: Various ugly syntax errors. Several people have given varyingly ugly solutions using other utilities, evals and so on. Your problem is how to get parameters into an awk program. The other solutions probably work, but I'm posting because of the general applicability of the technique I'm going to demonstrate here, not so much the specific example (I normally use sed for picking apart /etc/passwd) This technique is in some of the AT&T UNIX V3 UNIX documentation. And appears in many well written awk programs that have been published. I use it *very* extensively (10K+ awk scripts in production code): a=`awk -F: '$1 == "'$LOGNAME'" { print $5}'` Effectively what you want to do is enclose your script in single quotes, and surround any parameter you want to get in with single quotes again. The back-quoted command line is actually composed of *three* separate strings: 1) '$1 == "' 2) $LOGNAME 3) '" { print $5}' Only the second one is actually eval'd, the 1st and 2nd one aren't, the result is concatenated together then run as a command line. voila. T'other nice thing is that you don't go completely crazy trying to escape all of the shell metacharacters in the non-parameterized part of the awk program. Sooo, the awk script still looks pretty normal. In more substantial scripts it makes sense to use awk variables: a=`awk 'BEGIN { var1 = "'$var1'" var2 = "'$var2'" .... Actually, even tho it's kinda ugly, the $variable should also be enclosed in double quotes, ala: a=`awk -F: '$1 == "'"$LOGNAME"'" { print $5}'` Prevents you from being shot in the head by variables containing spaces and (most) other shell metacharacters. Disadvantage: introducing single quotes into the awk script is wierd... eg: a=`awk '{ printf "'"'"'" }'` -- Chris Lewis, R.H. Lathwell & Associates: Elegant Communications Inc. UUCP: {uunet!mnetor, utcsri!utzoo}!lsuc!eci386!clewis Phone: (416)-595-5425
gwc@root.co.uk (Geoff Clare) (09/23/89)
In article <1989Sep20.210951.10759@eci386.uucp> clewis@eci386.UUCP (Chris Lewis) writes: >In article <1163@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes: >> >>HELP!! I have been pulling my hair out over this seemingly simple >>problem: [ awk script deleted ] >Your problem is how to get parameters into an awk program. > >The other solutions probably work, but I'm posting because of the general >applicability of the technique I'm going to demonstrate here, not so much >the specific example (I normally use sed for picking apart /etc/passwd) > >This technique is in some of the AT&T UNIX V3 UNIX documentation. And >appears in many well written awk programs that have been published. >I use it *very* extensively (10K+ awk scripts in production code): > >a=`awk -F: '$1 == "'$LOGNAME'" { print $5}'` ^ /etc/passwd missing I find it much more readable, and less prone to error, to assign the necessary awk variables on the command line: a=`awk -F: '$1 == LOGNAME { print $5 }' LOGNAME="$LOGNAME" /etc/passwd` If the awk program is very long, this also means you can put it in a file for use with '-f', and still be able to set dynamic values for use in the program. The only problem with this method is if you want awk to read stdin. Most implementations incorrectly only read stdin if there are no arguments at all, not if there are no file arguments. However you can get round this by giving a file name of "-". -- Geoff Clare, UniSoft Limited, Saunderson House, Hayne Street, London EC1A 9HH gwc@root.co.uk (Dumb mailers: ...!uunet!root.co.uk!gwc) Tel: +44-1-315-6600
larry@macom1.UUCP (Larry Taborek) (09/25/89)
From article <1163@ispi.UUCP>, by jbayer@ispi.UUCP (Jonathan Bayer): > > HELP!! I have been pulling my hair out over this seemingly simple > problem: > > LOGNAME is set nicely here. However, when I try to do something similar > to /etc/passwd as follows: > a=" awk -F: '\$1 == \"$LOGNAME\" { > user=\$5; > print user > }'" > USER=`cat /etc/passwd | $a` > > I get the following error: > > awk: syntax error at source line 1 > context is > >>> ' <<< > awk: bailing out at source line 1 > Now, the following line does work (when I hardcode in LOGNAME): > USER=`cat /etc/passwd | awk -F: '$1 == "root" { user=$5; print user }'` > Jonathan Bayer Intelligent Software Products, Inc. > (201) 245-5922 500 Oakwood Ave. > jbayer@ispi.COM Roselle Park, NJ 07204 Jonathan, try this instead: USER=`cat /etc/passwd | awk -F: '{printf("%-8.8s %-20.20s\n",$1,$5)}'` echo $USER this works, but I think what you really want is: cat /etc/passwd | awk -F: '{printf("%-8.8s %-20.20s\n",$1,$5)}' without the USER=` the awk script basically prints the 1st and 5th fields in a printf statement, where the contents of $1 are put in a field 8 characters long left justified, and the contents of $5 are put into a field 20 characters long left justified. The \n should be a line feed. Hope this helps... Larry -- Larry Taborek ..!uunet!grebyn!macom1!larry Centel Federal Systems larry@macom1.UUCP 11400 Commerce Park Drive Reston, VA 22091-1506 703-758-7000
maart@cs.vu.nl (Maarten Litmaath) (09/27/89)
gs@diab.se (Greger Sernemar) writes:
\...
\a="`awk -F: '$1 == NAME {
\ user=$5;
\ print user
\ }' NAME=$LOGNAME - `"
\
\The last dash (-) closes standard input i.e enables other program to
\pipe to the awk script.
How can it pipe into awk when awk's stdin is closed?!
A dash doesn't mean CLOSE stdin, it means USE stdin!
\I was forced to either supply a file name or
\a dash to be able to set the awk variable.
\I'm not sure if this is a bug in the version of awk I'm using or not.
This is a bug indeed, present in SunOS 4.0.1 awk too.
Other bugs:
% awk -F '{print}'
awk: can't open {print}
% awk -F
awk: no argument for -f
%
--
`I AM NEW HEAR AMD I WANT TO INKRIMENT A |Maarten Litmaath @ VU Amsterdam:
VURIABLE BY 1 (OONE) IN "c"' (Tom Neff) |maart@cs.vu.nl, mcvax!botter!maart
dg@lakart.UUCP (David Goodenough) (09/28/89)
gwc@root.co.uk (Geoff Clare) sez: > clewis@eci386.UUCP (Chris Lewis) writes: >>This technique is in some of the AT&T UNIX V3 UNIX documentation. And >>appears in many well written awk programs that have been published. >>I use it *very* extensively (10K+ awk scripts in production code): >> >>a=`awk -F: '$1 == "'$LOGNAME'" { print $5}'` > ^ /etc/passwd missing > I find it much more readable, and less prone to error, to assign the > necessary awk variables on the command line: > > a=`awk -F: '$1 == LOGNAME { print $5 }' LOGNAME="$LOGNAME" /etc/passwd` > > The only problem with this method is if you want awk to read stdin. Try the following: awk < file >> otherfile 'BEGIN { np = '`head -1 $datadir/$job`' ml = "'$mailer'" jbu = "'`echo $job | tr a-z A-Z`'" dd = "'$datadir'" ta = "'$targ'" } rest of awk script follows .... Lets you get away with murder :-) Note that by judicious use of `` I can even get the output of a separate shell command into an awk variable: for example np gets a number from the first line of $datadir/$job -- dg@lakart.UUCP - David Goodenough +---+ IHS | +-+-+ ....... !harvard!xait!lakart!dg +-+-+ | AKA: dg%lakart.uucp@xait.xerox.com +---+
dg@lakart.UUCP (David Goodenough) (09/28/89)
From article <4926@macom1.UUCP>, by larry@macom1.UUCP (Larry Taborek): > try this instead: > > USER=`cat /etc/passwd | awk -F: '{printf("%-8.8s %-20.20s\n",$1,$5)}'` > echo $USER > > this works, ..... f::1000:31:Finger Pointer:/:/usr/guest/xfinger Not on the above it doesn't (think about it). I suggest: USER=`cat /etc/passwd | sed -e "s/::/:-:/" | \ awk -F: '{printf("%-8.8s %-20.20s\n",$1,$5)}'` -- dg@lakart.UUCP - David Goodenough +---+ IHS | +-+-+ ....... !harvard!xait!lakart!dg +-+-+ | AKA: dg%lakart.uucp@xait.xerox.com +---+
ganga@megadata.mega.oz (Ganga Varatharajan) (10/03/89)
From article <4926@macom1.UUCP>, by larry@macom1.UUCP (Larry Taborek): > > USER=`cat /etc/passwd | awk -F: '{printf("%-8.8s %-20.20s\n",$1,$5)}'` > echo $USER > > this works, but I think what you really want is: > > cat /etc/passwd | awk -F: '{printf("%-8.8s %-20.20s\n",$1,$5)}' > > without the USER=` I'm trying to alias d (csh) as: % dirs -l | awk '{ for (i = 1; i < NF+1; i++) { print i-1,$i } }' to list the directory stack one per line and numbered. % alias d "dirs -l | awk '{ for (i = 1; i < NF+1; i++) { print i-1,$i } }'" gives % $i undefined variable. % alias d 'dirs -l | awk \'{ for (i=1; i < NF+1; i++) { print i-1,$i}}\' ' gives % unmatched ' So I use % alias d "dirs -l | awk -f ~/.dirlist" which is slow. Any suggestions? Thanks Ganga.
ben@nsf1.mth.msu.edu (Ben Lotto) (10/05/89)
On 3 Oct 89 07:47:42 GMT, ganga@megadata.mega.oz (Ganga Varatharajan) said: Ganga> I'm trying to alias d (csh) as: Ganga> % dirs -l | awk '{ for (i = 1; i < NF+1; i++) { print i-1,$i } }' Ganga> to list the directory stack one per line and numbered. Try the following: alias d "dirs -l | awk '{ for (i = 1; i < NF+1; i++) { print i-1,"'$i'" } }'" The problem is that any variable is automatically evaluated when enclosed in double quotes. So when you get to the variable, end the double quotes and enclose the variable you want in single quotes. -- -B. A. Lotto (ben@nsf1.mth.msu.edu) Department of Mathematics/Michigan State University/East Lansing, MI 48824