home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / awk / awk_rev3.zip / AWK1.REV next >
Text File  |  1990-05-22  |  14KB  |  280 lines

  1.  
  2.  
  3.  
  4.           AWK under MS-DOS:  Programming Power for the Masses
  5.              Copyright (c) 1989, 1990, by George A. Theall
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.    When was the last time you were really excited by a computer language?
  13. "Can't remember", you say? Then check out AWK. Whether you use it for data
  14. manipulation or validation, program prototyping, or just general hacking,
  15. this versatile little language will improve your productivity immensely. 
  16.  
  17.  
  18.    Although first developed in 1977, AWK has only recently made its way
  19. into the MS-DOS world. Two companies, Mortice Kern Systems (MKS) and
  20. Polytron/SAGE Software, currently market and support implementations of
  21. AWK for around $100. Additionally, two non-commercial variants - one from
  22. Rob Duff and the other from the GNU Project - are available on some
  23. PC-oriented bbs's. Both offer all the capabilities of their commercial
  24. cousins for just the cost of a phone call. AWK is not a language with
  25. slick keyboard- or screen-handling operations so all three implementations
  26. should work on any machine running MS-DOS. In fact, I have used both MKS
  27. and Duff's AWK with no problems on a DEC Rainbow, a machine not exactly
  28. famous for its PC compatibility! :-)
  29.  
  30.  
  31.    Since the fall of 1988 I've worked with MKS AWK heavily, and I love it!
  32. It's become such an integral part of my toolkit that I don't feel I have
  33. done any work unless I've used AWK at least once each day. As for the
  34. other implementations, my experience is limited. I have, however, made
  35. some comparisons which should be of interest to those trying to choose
  36. among the four. [A summary of my comparisons can be found in the
  37. accompanying file AWK2.REV.] The rest of this discussion focuses not on
  38. any particular implementation but rather on the AWK language itself. 
  39.  
  40.  
  41.    The definitive source of information about AWK is _The AWK Programming
  42. Language_ by Aho, Kernighan, and Weinberger, the language's developers. 
  43. According to this book, AWK is "a pattern-matching language for writing
  44. short programs to perform common data-manipulation tasks". By design AWK
  45. trades off execution speed for a vast reduction in program development
  46. time making it perfect for one-shot tasks. Many common programming chores
  47. - opening files, reading lines, declaring variables, splitting lines into
  48. fields, etc... - are done automatically, so you spend more time on the
  49. basic design of the program. 
  50.  
  51.  
  52.    Like the SORT and MORE utilities supplied with MS-DOS AWK programs are
  53. text filters. That is, they read lines from one or more data files (or
  54. standard input if none are specified), process them in some fashion, and
  55. write them to standard output (normally the screen). With the characters
  56. '<' and '>' on a DOS commandline, it is possible to reassign standard
  57. input and output respectively to devices like the printer or disk files. 
  58. You invoke AWK either by including the program statements, enclosed in
  59. quotes, on the command line:
  60.  
  61.           AWK "program statements" datafiles
  62.  
  63. or, for longer programs, by specifying the name of a file containing those
  64. statements:
  65.  
  66.           AWK -f pgmfile datafiles
  67.  
  68. In both cases, "datafiles" refers to one or more data files to be
  69. processed. Each time AWK is invoked it interprets anew the program
  70. statements. 
  71.  
  72.  
  73.    Again, quoting from the book, "an AWK program is a sequence of patterns
  74. and actions that tell what to look for in the input data and what to do
  75. when it's found". Patterns can be either simple comparisons (like 'Errors
  76. > 9' or 'Name == "John"') or regular expression matches, a powerful way to
  77. work with character strings. [The '*' and '?' characters provide a limited
  78. type of regular expression matching for DOS file names.] Thus, the general
  79. form of an AWK program is:
  80.  
  81.           pattern1 { action1 }
  82.           pattern2 { action2 }
  83.           pattern3 { action3 }
  84.           ...
  85.  
  86. If a pattern is omitted, the action is applied to all records; if no
  87. action is supplied, records satisfying the pattern are simply written to
  88. standard output. Records can satisfy zero, one, or multiple patterns.  Two
  89. patterns with special meaning are BEGIN and END; they are used to specify
  90. actions performed before any records are read and after they've all been
  91. processed, respectively. Actions consist of one or more C-like programming
  92. statements. As AWK reads a data file it tests whether the current record
  93. satisfies any of the patterns; if so, the corresponding actions are taken
  94. sequentially. Comments start with a '#' and run to the end of the line. 
  95.  
  96.  
  97.    AWK reads records from the data files one at a time and splits them
  98. automatically into fields. By default records are separated by linefeeds;
  99. and fields, by blanks and/or tabs. If the situation demands it alternate
  100. record and field separators can be defined easily. The built-in variable
  101. NF represents the number of fields in the current record. The fields
  102. themselves are referenced using the '$' operator. Thus, $2 refers to the
  103. second field, $i to the ith field (for any integer i), and $NF to the last
  104. field in the current record. $0 denotes the entire record. Another
  105. built-in variable is NR; it equals the number of records read so far. So,
  106. for example, if you had a file in which there are supposed to be only four
  107. fields per line you could locate invalid lines with the following AWK
  108. code:
  109.  
  110.           # Print out lines with anything other than 4 fields. 
  111.           NF != 4 {
  112.                print NR, $0
  113.           }
  114.  
  115. Only invalid lines are printed here, preceded by a line number for
  116. identification purposes. By removing the pattern - and hence processing
  117. all lines - you could transform this into a line-numbering program. See
  118. how easy AWK can be?
  119.  
  120.  
  121.    Now imagine you want to redefine your PATH so frequently-used programs
  122. are accessed rapidly. To do this you'll need to locate all the programs on
  123. your disk and decide what's the best ordering of directories in the PATH.
  124. The second part's up to you, but what about the first part? How can you
  125. figure out where all your programs are? You could use DOS's CHKDSK command
  126. to list all the files on the disk, but you'd still be stuck with scanning
  127. through that list for lines ending in ".COM", ".EXE", or ".BAT".  A better
  128. solution would use CHKDSK to generate the list and then AWK to scan it for
  129. you. To do this, create the file ALLPROGS.AWK consisting of the single
  130. pattern:
  131.  
  132.           # Select records for executables only.
  133.           $0 ~ /\.(COM|EXE|BAT)$/
  134.  
  135. and then run it with the following DOS commandline:
  136.  
  137.           CHKDSK /v | awk -f ALLPROGS.AWK
  138.  
  139. What you'll see will be the full file names for just the executables -
  140. exactly what you want. [N.B. Since MS-DOS regards the characters '|', '<',
  141. and '>', as having special meanings it is not possible to include program
  142. statements with these characters on the DOS commandline. For this reason,
  143. we resort to ALLPROGS.AWK.]
  144.  
  145.  
  146.    How does this command work? The first part merely lists all files on
  147. the current drive, regardless of which directory they're in. The character
  148. '|' in the commandline instructs MS-DOS to "pipe" output from CHKDSK to
  149. AWK. The AWK program itself contains a single pattern but no action. This
  150. pattern selects lines for which the current record ends with one of three
  151. extensions: ".COM", ".EXE", or ".BAT". The operator '~' matches regular
  152. expressions, which are delineated by slashes. The trailing dollar sign in
  153. the regular expression anchors text at the end of a line. Given the format
  154. of CHKDSK's output, this pattern matchs only names of executable files.
  155. Since there's no specified action, AWK merely displays the matching lines
  156. on the screen. 
  157.  
  158.  
  159.    Or consider the following batch program, GREP.BAT. It searches through
  160. a file for lines containing a particular string:
  161.  
  162.           echo off
  163.           rem GREP.BAT - a string-search utility
  164.           rem     1st arg = string to search for
  165.           rem     2nd arg = file name to search
  166.           rem
  167.           AWK "$0 ~ /%1/ {print NR, $0}" %2
  168.  
  169. To find which lines in PDPROGS.DOC contain the string "Rainbow" you'd type
  170. "GREP Rainbow PDPROGS.DOC". If any matches are found AWK prints the lines
  171. preceded by their line numbers. By extending this technique a bit you
  172. could develop a free-form database with records spanning an arbitrary
  173. number of lines and use AWK to search for particular entries. [Hint:
  174. separate records with a blank line and redefine AWK's record separator.]
  175.  
  176.  
  177.    In AWK variables can be treated as either strings or numbers; AWK
  178. infers a variable's type from its context. In converting from strings to
  179. numbers AWK returns the leading portion of a string that "looks" like a
  180. number, or else zero. For instance, the string "12.5" becomes the number
  181. 12.5; "896K" becomes 896; and "NotANumber" becomes 0. To give you an idea
  182. how useful this feature is consider this example: Using a file of country
  183. names ($1), populations ($2), and gross national products ($3), you'd like
  184. to compare how well-off the "average" citizen is in various countries
  185. based on per-capita gross national product figures. But before you say
  186. "Piece o' cake, it's just $3/$2", let's add a twist: Suppose figures for
  187. GNP and total population are not always available. With AWK, this extra
  188. complication only requires a simple test:
  189.  
  190.           # Calculates per-capita GNP for various countries
  191.           #    Missing values were coded as "n/a".
  192.           if ( ($2 == "n/a") || ($3 == "n/a") )
  193.                print "Data not available for", $1
  194.           else
  195.                print "Per-capita GNP for", $1, "equals", $3/$2
  196.  
  197. Were it not for the test, missing data would lead to either divide-by-zero
  198. errors (no figures for population) or reports of 0 per-capita GNP (no data
  199. on GNP).
  200.  
  201.  
  202.    One feature of AWK not found in most programming languages is that of
  203. associative arrays - arrays indexed by strings! For instance, you could
  204. have an array named SALARY[] and refer to an element as SALARY["John"]. 
  205. AWK also has a rich set of mathematical and character functions: system(),
  206. getline(), index(), printf(), split(), substr(), length(), sqrt(), sin(),
  207. log(), rand(), etc... And if you're not satisfied with what AWK provides,
  208. you can even define your own functions. 
  209.  
  210.  
  211.    As a final illustration of AWK's capabilities I'll present without
  212. explanation a quick & dirty spelling-checker:
  213.  
  214.           # SPELL.AWK - List words occurring only once in a document.
  215.           #    A "word" is defined as a sequence of alphanumerics
  216.           #    or underscores.
  217.  
  218.           # Scan thru each line and compute word frequencies.
  219.           # The associative array Words[] holds these frequencies.
  220.           {
  221.                # replace non-alphanumerics with blanks throughout line 
  222.                gsub(/[^A-Za-z0-9_]/, " ")
  223.  
  224.                # count how many times each word used
  225.                for (i = 1; i <= NF; i++)     # scan all fields ... 
  226.                     Words[$i]++              #    increment word count 
  227.           }
  228.  
  229.           # Print out infrequently-used words.
  230.           END {
  231.                for (w in Words)              # scan over all words ... 
  232.                     if (Words[w] == 1)       #    if word used once ... 
  233.                          print w             #         print it
  234.           }
  235.  
  236. This is a spelling-checker only in a very loose sense. The basic premise
  237. behind it is that any word appearing just once in a large document is
  238. likely to be misspelled. The idea is simple and doesn't require a
  239. dictionary. Further, it may be useful to programmers who need to spot
  240. variables or functions that are declared but never used in a program. Try
  241. doing that with a regular spelling-checker!!!
  242.  
  243.  
  244.    In this discussion my goal has been to show how versatile, powerful,
  245. and useful AWK can be. Time limitations have kept me from covering more of
  246. its capabilities. True, AWK is not perfect for every task, but if you're
  247. serious about using your computer, you should make it part of your
  248. toolkit.
  249.  
  250.  
  251.    The AWK implementations sold by MKS and Polytron both list for $99 and
  252. include the book by Aho, Kernighan, and Weinberger. MKS' approach seems to
  253. be the following: Follow the book to the letter and give the user a
  254. choice. Besides several useful utilities, the MKS package consists of four
  255. AWK executables: large- and small-memory models with and without 80x87
  256. support. All four conform closely to the language specifications - no
  257. omissions and virtually no extensions. There's also a brief reference
  258. guide, but its presentation is probably too condensed for beginners. 
  259. Polytron takes a different tack: Extend the language a bit and put it all
  260. into a single executable. If you only use AWK under MS-DOS you'll be
  261. pleased with the extra features: get/set environment variables, convert to
  262. upper-/lowercase, and manipulate variables in a bitwise fashion, to name
  263. just a few; else, you're likely to be bothered by portability problems. 
  264. MKS can be reached at 1-800-265-2797; Polytron, at 503-645-1150; and Rob
  265. Duff at 1:153/713 (FidoNet) or 1-604-251-1816 (BBS). For information about
  266. GNU AWK, contact Kent Williams (williams@umaxc.weeg.uiowa.edu) or Jay
  267. Fenlason at 617-253-8975.
  268.  
  269.  
  270.    Disclaimer: Apart from being a satisfied owner of Mortice Kern System's
  271. AWK and Polytron's PolyShell, I have no direct connection with the
  272. companies mentioned above. 
  273.  
  274.  
  275.    If you have any comments about this article, or the AWK language in
  276. general, please get in touch. For those with email access, I can be
  277. reached as GTHEALL@PENNDRLS (BITNET) or GTHEALL@PENNDRLS.UPENN.EDU
  278. (Internet). Otherwise, give me a call at +1 215 898 3419.
  279.  
  280.