[comp.unix.shell] awk question

me@cbnewsh.att.com (william.j.bruncati) (01/19/91)

I am having a problem with an awk program.
What I'm trying to do is have an array element
match on a pattern in the first field. 
I can match on the fixed string
but not the pattern. Can anyone help?

This works.
		if (myarray[i] == $1 )
			print $0

This doesn't work. It won't give me a match although there is one.
		if (myarray[i] ~ /$1/ )
			print $0

Also, while I'm posting, could someone tell me if it's possible
to have  nested case statements in shell?

					Thanks in advance,
						Bill Bruncati

bob@wyse.wyse.com (Bob McGowen x4312 dept208) (01/20/91)

In article <1991Jan18.164243.11804@cbnewsh.att.com> me@cbnewsh.att.com (william.j.bruncati) writes:
>I am having a problem with an awk program.
>What I'm trying to do is have an array element
>match on a pattern in the first field. 
>I can match on the fixed string
>but not the pattern. Can anyone help?
>
>This works.
>		if (myarray[i] == $1 )
>			print $0
>
>This doesn't work. It won't give me a match although there is one.
>		if (myarray[i] ~ /$1/ )
>			print $0

  I believe this is because you are using "old" awk, which did not
  allow substitution into patterns, as with your "/$1/".  Check to
  see if you have executables named "oawk" and "nawk".  If so, "oawk"
  will most likely be linked to "awk", so you will want to change
  the command to "nawk".

>Also, while I'm posting, could someone tell me if it's possible
>to have  nested case statements in shell?

  Yes, assuming you use sh.I do not know about csh.  I have on occasion
  used the following to step through all arguments looking for options
  and then checking the options to see if they are legal ones:

     for arg in $*  # assume no args will have white space
     do
	case $arg in
	-*)	# this is an option
	   case $arg in
	   -h)
	   ;;
	   -p)
	   ;;
	   -x)
	   ;;
	   -*)
	   ;;
	   esac
	*)	# this is not an option
	   item="$item $arg"
	esac
    done
>					Thanks in advance,
>						Bill Bruncati

I hope this is useful.

Bob McGowan  (standard disclaimer, these are my own ...)
Product Support, Wyse Technology, San Jose, CA
..!uunet!wyse!bob
bob@wyse.com

tchrist@convex.COM (Tom Christiansen) (01/20/91)

From the keyboard of bob@wyse.UUCP (Bob McGowen x4312 dept208):
:In article <1991Jan18.164243.11804@cbnewsh.att.com> me@cbnewsh.att.com (william.j.bruncati) writes:
:>This doesn't work. It won't give me a match although there is one.
:>		if (myarray[i] ~ /$1/ )
:>			print $0
:
:  I believe this is because you are using "old" awk, which did not
:  allow substitution into patterns, as with your "/$1/".  Check to
:  see if you have executables named "oawk" and "nawk".  If so, "oawk"
:  will most likely be linked to "awk", so you will want to change
:  the command to "nawk".
:

And if like so many all you have is the old awk, get gawk, which is free.
You can also get perl, is a proper superset of all the awks (it comes
with awk-to-perl and sed-to-perl translators) and is also free.

--tom
--
"Hey, did you hear Stallman has replaced /vmunix with /vmunix.el?  Now
 he can finally have the whole O/S built-in to his editor like he
 always wanted!" --me (Tom Christiansen <tchrist@convex.com>)

jay@silence.princeton.nj.us (Jay Plett) (01/21/91)

In article <1991Jan20.062150.24582@convex.com>, tchrist@convex.COM (Tom Christiansen) writes:
- From the keyboard of bob@wyse.UUCP (Bob McGowen x4312 dept208):
- :In article <1991Jan18.164243.11804@cbnewsh.att.com> me@cbnewsh.att.com (william.j.bruncati) writes:
- :>This doesn't work. It won't give me a match although there is one.
- :>		if (myarray[i] ~ /$1/ )
- :>			print $0
- :
- :  I believe this is because you are using "old" awk, which did not
- :  allow substitution into patterns, as with your "/$1/".
- 
- And if like so many all you have is the old awk, get gawk, which is free.

Either nawk or gawk are worth having.  But I don't believe that either
of them will solve the stated problem.

I've never been able to find a way to use a variable on the right-hand
side of a ~ expression with any of the incarnations of awk.  Have I
missed something?

	...jay

tchrist@convex.COM (Tom Christiansen) (01/21/91)

From the keyboard of jay@silence.princeton.nj.us (Jay Plett):
:I've never been able to find a way to use a variable on the right-hand
:side of a ~ expression with any of the incarnations of awk.  Have I
:missed something?

Hmm, now that you mention it, there's no way for awk to distinguish

    if (myarray[i] ~ /foo/)

is the literal or the variable foo.  I guess that's the price you pay for
not having variable markers as you do in the shell or perl.  Certainly in
perl there's a big difference between

    if ($myarray[$i] =~ /foo/)	# can't use ~ -- that's bitwise negation, per C
and
    if ($myarray[$i] =~ /$foo/)

I shall say no more. :-)

--tom
--
"Hey, did you hear Stallman has replaced /vmunix with /vmunix.el?  Now
 he can finally have the whole O/S built-in to his editor like he
 always wanted!" --me (Tom Christiansen <tchrist@convex.com>)

dag@fciva.FRANKCAP.COM (Daniel A. Graifer) (01/21/91)

In article <1991Jan20.232154.29651@convex.com> tchrist@convex.COM (Tom Christiansen) writes:
>From the keyboard of jay@silence.princeton.nj.us (Jay Plett):
>:I've never been able to find a way to use a variable on the right-hand
>:side of a ~ expression with any of the incarnations of awk.  Have I
>:missed something?
>
>Hmm, now that you mention it, there's no way for awk to distinguish
>
>    if (myarray[i] ~ /foo/)
>
>is the literal or the variable foo. 

$ nawk 'BEGIN{
x="aw fubar anyways"
foo="bar"
if ( x ~ foo )
	print "Yep"
else
	print "Nope"
}'
Yep
$ nawk 'BEGIN{
x="aw fubar anyways"
foo="b.r"
if ( x ~ foo )
	print "Yep"
else
	print "Nope"
}'
Yep

'nuff said

Dan

-- 
Daniel A. Graifer			Coastal Capital Funding Corp.
Sr. Vice President, Financial Systems	7900 Westpark Dr. Suite A-130
(703)821-3244				McLean, VA  22102
uunet!fciva!dag				fciva.FRANKCAP.COM!dag@uunet.uu.net

]) (01/22/91)

In article <681@silence.princeton.nj.us> jay@silence.princeton.nj.us (Jay Plett) writes:
>In article <1991Jan20.062150.24582@convex.com>, tchrist@convex.COM (Tom Christiansen) writes:
>- From the keyboard of bob@wyse.UUCP (Bob McGowen x4312 dept208):
>- :In article <1991Jan18.164243.11804@cbnewsh.att.com> me@cbnewsh.att.com (william.j.bruncati) writes:
>- :>This doesn't work. It won't give me a match although there is one.
>- :>		if (myarray[i] ~ /$1/ )
>- :>			print $0
>- :
>- :  I believe this is because you are using "old" awk, which did not
>- :  allow substitution into patterns, as with your "/$1/".
>- 
>- And if like so many all you have is the old awk, get gawk, which is free.
>
>Either nawk or gawk are worth having.  But I don't believe that either
>of them will solve the stated problem.
>
>I've never been able to find a way to use a variable on the right-hand
>side of a ~ expression with any of the incarnations of awk.  Have I
>missed something?

Well, in nawk, this works...

	if ( match(myarray[i], $1) > 0 ) {
		print "record", NR, "matched somewhere on entry", i
		print $0
		}
	if ( match(myarray[i], $1) == 1 ) {
		print "record", NR, "matched start of array item", i
		print $0
		}

In a related vein, I often do something like this...

	BEGIN {
		keywords = " first second third "
		ebadkey = "invalid keyword '%s' on record %d\n"
		}

	#
	# Handle a valid keyword
	#
	$1 == "key" && match(keywords, " " $2 " " {
		print "I'd do something with the key, " $2 ", here."
		next
		}

	#
	# Bad keyword record!
	#
	$1 == "key" {
		printf(ebadkey, $2, NR) | "/bin/cat 1>&2"
		errorcount++
		next
		}

	#
	# Report error count
	#
	END {
		if ( errorcount > 0 )
			print errorcount, "errors found" | "/bin/cat 1>&2"
		}

...Kris
-- 
Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS
Amdahl Corporation   |                |                    |
     [The opinions expressed above are mine, solely, and do not    ]
     [necessarily reflect the opinions or policies of Amdahl Corp. ]

tchrist@convex.COM (Tom Christiansen) (01/22/91)

From the keyboard of dag@fciva.UUCP (Daniel A. Graifer):
:In article <1991Jan20.232154.29651@convex.com> I said:
:>:I've never been able to find a way to use a variable on the right-hand
:>:side of a ~ expression with any of the incarnations of awk.  Have I
:>:missed something?
:>
:>Hmm, now that you mention it, there's no way for awk to distinguish
:>
:>    if (myarray[i] ~ /foo/)
:>
:>is the literal or the variable foo. 
:
:$ nawk 'BEGIN{

Ah, a _nawk solution.  Shoulda known. :-)  I had perl two years
before I got gawk, and the awk on my system is still the old one.

thanks,

-tom
--
"Hey, did you hear Stallman has replaced /vmunix with /vmunix.el?  Now
 he can finally have the whole O/S built-in to his editor like he
 always wanted!" --me (Tom Christiansen <tchrist@convex.com>)

haozhou@acsu.buffalo.edu (Hao Zhou) (02/28/91)

I am using awk to print some selected lines from a text file. What I
want to to is to hold off the current line until next line comes in
and a certain condition is satisfied before printing both lines. So I
need to store the current line in some variable as follows:

	prev = 'initialization'
	awk '{{if (condition) \
		printf("%s \n %s \n", $prev, $0)} 
	      {prev=$0}}'

However the variable prev doesn't store the previous line. Instead the
printf prints out twice the current line. What am I doing wrong?

Thanks for any help on this problem.


	Hao
	
-- 
Internet:haozhou@acsu.buffalo.edu BITNET:haozhou%acsu.buffalo.edu@UBVM.BITNET
UUCP: rutgers!ub!haozhou

jik@athena.mit.edu (Jonathan I. Kamens) (02/28/91)

In article <62322@eerie.acsu.Buffalo.EDU>, haozhou@acsu.buffalo.edu (Hao Zhou) writes:
|> 	prev = 'initialization'
|> 	awk '{{if (condition) \
|> 		printf("%s \n %s \n", $prev, $0)} 
|> 	      {prev=$0}}'
|> 
|> However the variable prev doesn't store the previous line. Instead the
|> printf prints out twice the current line. What am I doing wrong?

  First of all, what is the first line of the script,

    prev = 'initialization'

supposed to be doing?  Since that command appears outside of the awk command,
it sets a shell variable, not an awk variable!

  Second, variables in awk are not referred to using '$' -- only line fields
are.  So the "$prev" in the printf above should just be "prev".  It's likely
that in "$prev", prev is getting interpreted as a number, and since it's a
string awk ends up thinking that it's equal to 0, and therefore uses $0, which
is why the same line prints twice.

  Third, where's the condition?

  It looks to me like you tried to cut down the code you're actually using in
order to post a short example to the net, and you managed to butcher it up
enough in the process that it's not easy for us to help you.  But I'll try:

    awk 'BEGIN { prev = "" }
    { if (condition) prinf("%s\n%s\n", prev, $0) }
    { prev = $0 }'

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

art@pilikia.pegasus.com (Art Neilson) (02/28/91)

In article <62322@eerie.acsu.Buffalo.EDU> haozhou@acsu.buffalo.edu (Hao Zhou) writes:
>I am using awk to print some selected lines from a text file. What I
>want to to is to hold off the current line until next line comes in
>and a certain condition is satisfied before printing both lines. So I
>need to store the current line in some variable as follows:
>
>	prev = 'initialization'
>	awk '{{if (condition) \
>		printf("%s \n %s \n", $prev, $0)} 
>	      {prev=$0}}'
>
>However the variable prev doesn't store the previous line. Instead the
>printf prints out twice the current line. What am I doing wrong?
>
>Thanks for any help on this problem.
>
>
>	Hao
>	
>-- 
>Internet:haozhou@acsu.buffalo.edu BITNET:haozhou%acsu.buffalo.edu@UBVM.BITNET
>UUCP: rutgers!ub!haozhou

All your curly braces are quite confusing.
This looks like what you're trying to do.

awk '
BEGIN {
	prev = 'initialization'
}
{
	if (condition)
		printf("%s \n %s \n", prev, $0)
	prev = $0
}'
-- 
Arthur W. Neilson III		| INET: art@pilikia.pegasus.com
Bank of Hawaii Tech Support	| UUCP: uunet!ucsd!nosc!pegasus!pilikia!art

mjm@eleazar.dartmouth.edu (Andy Behrens) (03/01/91)

haozhou@acsu.buffalo.edu (Hao Zhou) writes:
> I am using awk to print some selected lines from a text file. What I
> want to to is to hold off the current line until next line comes in
> and a certain condition is satisfied before printing both lines. 
>
>	awk '{{if (condition) \
>		printf("%s \n %s \n", $prev, $0)} 
>	      {prev=$0}}'
>
>However the variable prev doesn't store the previous line. Instead the
>printf prints out twice the current line. What am I doing wrong?

You should write 'prev' instead of '$prev'.  Awk variables (unlike
shell variables) are written without a dollar sign.

The awk statements

	n="3"
	print $n	# or print $(n)

will print the third field of the input line.

--
If you've got a hammer,			       If the only tool you have
find a nail.				    is a hammer, you tend to see
(George Bush, January 29, 1991)			every problem as a nail.
							(Abraham Maslow)
+-------------------+
|  Andy Behrens     |                   or: andyb%coat.com@dartmouth.edu
|  andyb@coat.com   |                    bitnet: andyb%coat.com@dartcms1
+-------------------+       uucp: {uunet,rutgers}!dartvax!coat.com!andyb
RFD #1, Box 116, East Thetford, Vt. 05043                 (802) 649-1258
Burlington Coat, HC 61 Box 1B, Lebanon, N.H. 03766        (603) 448-5000