[comp.unix.questions] Using pipes within awk programs

gwc@root.co.uk (Geoff Clare) (01/13/88)

I have discovered that it is possible to send data down a pipe from
within an awk program.  For example

	who | awk '{ print $1 | "sort" }'

gives the same output as

	who | awk '{ print $1 }' | sort

I have tried this on a whole variety of flavours of UNIX, and it
works on all of them.

My question is this:  I can't find any reference to this feature
in any of our awk manuals, so is it safe to use it? and will it
work on ALL systems or just some of them?  (I have tried it on
Uniplus+ V.2, BSD4.2, HP-UX, Sequent DYNIX, Tolerant TX).

Any awk gurus out there? (or authors?!?).

Answers to my specific question by email please, and I will summarise;
but please don't inundate my mail box with general discussions of
undocumented awk features - feel free to post those to the net.
-- 

Geoff Clare              gwc@root.co.uk            seismo!mcvax!ukc!root44!gwc

ok@quintus.UUCP (Richard A. O'Keefe) (01/15/88)

In article <515@root44.co.uk>, gwc@root.co.uk (Geoff Clare) ask
about using pipes within awk programs.

This feature is described in the book
	The AWK Programming Language
	Aho, Kernighan, & Weinberger
	Addison-Wesley
	ISBN 0-201-07981-X
	US$ 22

Page 62 (The getline function):
	Cmd | getline		-- sets $0 and NF
	Cmd | getline Var	-- sets Var
The command is executed ONCE, just as a <file in that position
is opened ONCE.  All forms of getline return
	-1 if an error occurred
	 0 if end of file was encountered
	 1 if a record was read

Page 58 (Output into Pipes):
	print Stuff | Command
	printf(Format,Exprs) | Command
The command is executed ONCE, just as a >File in that position
is opened ONCE.

Page 59 (Closing Files and Pipes):
	close("...")
closes a pipe or a file.

BEWARE:  files and pipes share a name space.  That is, if AWK
sees
	print Entry >>"cat"
it will open a FILE called "cat" and from then on "cat" will
designate that file.  But if it sees
	print Remark | "cat"
it will open a PIPE, and from then on "cat" will designate that
pipe.  close("cat") will close either a file or a pipe, depending
on what the string was associated with.  Avoid file names that
look like commands.

In SunOS 3.2,	print | "cmd" works
	  but	"cmd" | getline doesn't.

Anyone who is interested in mastering AWK should at least read this
book.  It describes the latest version, so there are some features
(like user-defined functions, alas) which may not be available in
the version you're using.  The latest version is available for MS-DOS...

hugh@BRL.ARPA (USAFAS | Howard) (01/16/88)

Hi,

	I don't know if it is allowed in all versions of unix, but it does
work on Xenix 3.4 running on an Intel 310.

	It is described pages 170 and 171 of the ATT Unix System V Programmers
Guide.

hugh@brl

dph@beta.UUCP (David P Huelsbeck) (01/16/88)

In article <537@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>In article <515@root44.co.uk>, gwc@root.co.uk (Geoff Clare) ask
>about using pipes within awk programs.
>
>This feature is described in the book
>	The AWK Programming Language
>	Aho, Kernighan, & Weinberger
>	Addison-Wesley
>	ISBN 0-201-07981-X
>	US$ 22
>
	[...]
>
>Page 59 (Closing Files and Pipes):
>	close("...")
>closes a pipe or a file.
>
	
	I believe that this feature is not common
	to most awks.  It will not work for most
	poor folks with the plain old vanilla awk,

>Anyone who is interested in mastering AWK should at least read this
>book.  It describes the latest version, so there are some features
>(like user-defined functions, alas) which may not be available in
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>the version you're using.  The latest version is available for MS-DOS...
 ^^^^^^^^^^^^^^^^^^^^^^^^

	What are they charging for the new version?
	Does it come with source or does that cost
	you mega-dollars?  

	Poor folks can get GNU awk (gawk) from prep.ai.mit.edu.
	I've never tried it, but from the source I'd say it's
	not new-awk-compatable.


	David Huelsbeck
	dph@lanl.gov.arpa
	{ihnp4|cmcl2}!lanl!dph


	

ivor@geac.UUCP (Ivor Williams) (01/18/88)

In article <515@root44.co.uk> you write:
>	who | awk '{ print $1 | "sort" }'
>
>gives the same output as
>
>	who | awk '{ print $1 }' | sort

FYI, the two *don't* give the same results under Ultrix T2.0-1I.

Ivor
-- 
Ivor Williams, Geac Computers International Inc. 
UUCP:	{mnetor|yetti|utgpu}!geac!ivor

mkhaw@teknowledge-vaxc.ARPA (Mike Khaw) (01/21/88)

>> >	who | awk '{ print $1 | "sort" }'

>> >	who | awk '{ print $1 }' | sort

>> FYI, the two *don't* give the same results under Ultrix T2.0-1I.

> Then Ultrix must be seriously broken, to not allow standard

I think Ultrix awk is older than 4.3bsd's "old" awk.  On Ultrix 1.2,
the first form of pipe prints nothing.  The second form prints a sorted
list of logged in users.  Ultrix 1.2's awk also has the bug where
things like

	echo foo bar | awk '{ tmp = $1; $1 = $2; $2 = tmp; print $1, $2 }'

don't work.  That's how old it is.

Mike Khaw
-- 
internet:  mkhaw@teknowledge-vaxc.arpa
usenet:	   {uunet|sun|ucbvax|decwrl|uw-beaver}!mkhaw%teknowledge-vaxc.arpa
USnail:	   Teknowledge Inc, 1850 Embarcadero Rd, POB 10119, Palo Alto, CA 94303

rupley@arizona.edu (John Rupley) (01/22/88)

In article <2138@geac.UUCP>, ivor@geac.UUCP (Ivor Williams) writes:
> In article <515@root44.co.uk> you write:
> >	who | awk '{ print $1 | "sort" }'
> >gives the same output as
> >	who | awk '{ print $1 }' | sort
> 
> FYI, the two *don't* give the same results under Ultrix T2.0-1I.

Then Ultrix must be seriously broken, to not allow standard
usage of sort and awk. Diff shows identical output for the above
two command lines, under BSD4.3 (old awk) and SysV rel2 (new awk).

John Rupley
    internet: rupley@megaron.arizona.edu
    uucp: ..{ihnp4 | hao!noao}!arizona!rupley
    Dept. Biochemistry, Univ. Arizona, Tucson  AZ  85721

dph@beta.UUCP (David P Huelsbeck) (01/23/88)

In article <3521@megaron.arizona.edu> rupley@arizona.edu (John Rupley) writes:
>In article <2138@geac.UUCP>, ivor@geac.UUCP (Ivor Williams) writes:
>> In article <515@root44.co.uk> you write:
>> >	who | awk '{ print $1 | "sort" }'
>> >gives the same output as
>> >	who | awk '{ print $1 }' | sort
>> 
>> FYI, the two *don't* give the same results under Ultrix T2.0-1I.
>
>Then Ultrix must be seriously broken, to not allow standard
>usage of sort and awk. Diff shows identical output for the above
>two command lines, under BSD4.3 (old awk) and SysV rel2 (new awk).


Yes. Ultrix awk is broken in more ways than that.  I haven't tried
this particular awk bug on BSD4.2 but I'll bet it's broken there too.

BSD4.2 made some changes to awk.  Since 4.3 came out very shortly
after I became interested in awk I've never looked to see exactly 
what they did or why. However the changes they made introduced some
errors that didn't exist before and were fixed in 4.3.  The most
obvious was that "$1 = foo" did not change the value of $0. So the
old swaping two items in a line while leaving the rest intact didn't
work any more.  This was known by the time Ultrix came out but I guess
they wanted to be bug for bug compatable. ;-)

	David Huelsbeck
	dph@lanl.gov.arpa
	{cmcl2|ihnp4}!lanl!dph

cmf@cisunx.UUCP (Carl M. Fongheiser) (01/23/88)

In article <20466@teknowledge-vaxc.ARPA> mkhaw@teknowledge-vaxc.ARPA (Mike Khaw) writes:
]>> >	who | awk '{ print $1 | "sort" }'
]
]>> >	who | awk '{ print $1 }' | sort
]
]>> FYI, the two *don't* give the same results under Ultrix T2.0-1I.
]
]> Then Ultrix must be seriously broken, to not allow standard
]
]I think Ultrix awk is older than 4.3bsd's "old" awk.  On Ultrix 1.2,
]the first form of pipe prints nothing.  The second form prints a sorted
]list of logged in users.  Ultrix 1.2's awk also has the bug where
]things like
]
]	echo foo bar | awk '{ tmp = $1; $1 = $2; $2 = tmp; print $1, $2 }'
]
]don't work.  That's how old it is.
]
]Mike Khaw

That's funny -- I just tried these commands under both Ultrix 1.2 and 2.0.
They worked fine!  Incidentally, there is a difference between the
first two commands.  On Ultrix, the output of sort appears asynchronously
when sort is started by awk -- as if awk didn't do a wait() on the process.

				Carl Fongheiser
				University of Pittsburgh
				Computing & Information Systems
				...!pitt!cisunx!cmf
				cmf@pittvms.BITNET
				cmf%vms.cis.pittsburgh.edu@vb.cc.cmu.edu

jc@minya.UUCP (01/24/88)

In article <2138@geac.UUCP>, ivor@geac.UUCP (Ivor Williams) writes:
> In article <515@root44.co.uk> you write:
> >	who | awk '{ print $1 | "sort" }'
> >gives the same output as
> >	who | awk '{ print $1 }' | sort
> 
> FYI, the two *don't* give the same results under Ultrix T2.0-1I.

Nor on this Sys/V machine, and I am rather mystified at the difference.
The second produces output like I expect.  My prompt is set up to show
the current directory, so what I see on my screen when I use the second
command is:
| 	/usr/jc: who | awk '{ print $1 }' | sort
| 	jc
| 	std
| 	/usr/jc:

However, when I try the first command, the screen looks like:
|	/usr/jc: who | awk '{ print $1 | "sort" }'
|	/usr/jc: jc
|	std

In other words, I get a new shell prompt, and THEN I get the output
from the command.  There was no '&' anywhere in the line.  Does anyone
have an explanation as to why the output was delayed like this?  It
looks like awk is starting the sub-process and exiting without waiting
for it to complete.  I find this a bit surprising, not to mention a
bit weird.  Consider also:

|	/usr/jc: who | awk '{ print $1 | "sort" }' |wc
|      2      2      7

This appears to work correctly, so I clearly don't understand what's
going on here.

-- 
John Chambers <{adelie,ima,maynard,mit-eddie}!minya!{jc,root}> (617/484-6393)