home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 1 / CDPD_Vol1.bin / pd / 101-125 / 102 / match_stuff / mat.doc < prev    next >
Text File  |  1992-06-23  |  47KB  |  1,082 lines

  1.   ============================================================================
  2.  ||                                                                        ||
  3.  ||     MAT -- p.n.; poss. abbrev. of "Match"; also "Matte" [Motion        ||
  4.  ||          Picture Arts]: means of cutting, inserting and superposing    ||
  5.  ||          disparate items.                                              ||
  6.  ||                                                                        ||
  7.  ||                         -------------------                            ||
  8.  ||                                                                        ||
  9.  ||     This program provides a flexible string-matching and substitution  ||
  10.  ||     mechanism for both text and filenames.  It will probably be most   ||
  11.  ||     useful within command script files to extend the operations        ||
  12.  ||     possible with AmigaDOS.  The matching scheme is an extended        ||
  13.  ||     version of the standard AmigaDOS pattern-matching convention,      ||
  14.  ||     with the added features of negation and "slicing" of matched       ||
  15.  ||     strings.                                                           ||
  16.  ||                                                                        ||
  17.  ||         *   Searches for patterns within text files.                   ||
  18.  ||                                                                        ||
  19.  ||         *   Rearranges text within matched lines to                    ||
  20.  ||             create new files.                                          ||
  21.  ||                                                                        ||
  22.  ||         *   Searches directories for matching file names.              ||
  23.  ||                                                                        ||
  24.  ||         *   Creates Command Script Files using the whole or            ||
  25.  ||             parts of matched filenames.                                ||
  26.  ||                                                                        ||
  27.  ||                                                                        ||
  28.  ||                              -- Copyright (C)1987  Peter J. Goodeve -- ||
  29.  ============================================================================
  30.  
  31.  
  32.                         -- by Pete Goodeve --
  33.  
  34.                              August 1987
  35.  
  36.     This is one of those programs that is probably overkill for most
  37. purposes, but on rare occasions may do something that no other program can.
  38. It grew out of some long-time desires I've had while working with the Amiga
  39. (...and grew... and grew...).  First, I wanted to be able to search text
  40. files for more than just simple strings: I wanted full pattern-matching
  41. ability. Second, I wanted to be able to do things equivalent to this sort
  42. of "impossible" command:
  43.  
  44.         "RENAME myfile#? AS myfile_backup#?"
  45.  
  46.  
  47.     Eventually, some tortuous evolution led to a single program, "Mat",
  48. that combines both facilities into one (because 90% of the code was
  49. common).  Along the way, I extended Richards' original matching algorithm
  50. -- recoded in C from BCPL -- to handle negation patterns ("don't match the
  51. string if this pattern matches"), the "*" as an optional alternative to
  52. "#?", and the marking of "slice points" in the matched string so it can
  53. later be cut into pieces and spliced with other text.
  54.  
  55.     The resulting program is much more flexible than "Search" or any of the
  56. file matching commands, but it is not by any means a full language like,
  57. say, "awk".  Because of its flexibility, the command line syntax can get a
  58. little involved compared to other DOS commands, so it is probably easiest
  59. to use within prepared script files.  With a command syntax like that, of
  60. course, Mat can't be invoked from a WorkBench icon, only from a CLI.
  61.  
  62.     A couple of things I should also mention at this early opportunity.
  63. In distinction to "Search" -- which is a simple string search -- this is a
  64. line-matching program.  In other words the pattern you specify must match
  65. the whole line; if the pattern you are looking for can occur anywhere on
  66. the line (an "unanchored" pattern) it must be preceded and followed by
  67. wild-cards ("#?" or "*").  You will also find that pattern matching can be
  68. SLOWW!  On a simple (unanchored) string search it is about half the speed
  69. of "Search", and each alternation you add increases the time by about the
  70. simple-search time: it is doing a lot of work on each character in the
  71. file.  On the other hand, anchored matches can be quite fast, because each
  72. line scan can quit at the first failure.  You may find it preferable to RUN
  73. the program as a background process; it works nicely with "pipes" if you
  74. have them installed.
  75.  
  76.     The program can essentially operate in two different modes: 1) it can
  77. scan text files for lines matching a specified pattern; 2) it can scan
  78. directories for filenames matching patterns.  In either case matched
  79. strings can either be output unchanged or they can be cut up (according to
  80. "slice marks" in the pattern) and rearranged -- possibly with added text
  81. --on the basis of a supplied "template".  As well as pieces of the source
  82. string, things like line-count and current filename can be spliced into the
  83. output. (There are actually two more modes.  In one you can perform the
  84. same sort of operations on literal arguments in the command line; this is
  85. only really intended for the rare occasion you might want to do some
  86. complex test or operation on a command script argument.  The other mode
  87. sends the contents of the specified files in sequence to the standard
  88. output with no processing at all -- it's a little more flexible than JOIN.)
  89. All control is from the command line; a specific syntax -- possibly
  90. including keywords -- determines each form.
  91.  
  92.     Before getting into a complete description, some specific examples
  93. might give a flavor of what it can do.
  94.  
  95.  
  96.         MAT *(word|another)* myfile
  97.  
  98. Mat scans "myfile" for lines containing "word" or "another", and displays
  99. them on screen.  (Or of course you could redirect them to a desired file
  100. with the ">" convention.)  Note the <any-string> markers ("*") surrounding
  101. the main pattern so that it is unanchored.
  102.  
  103.  
  104.         MAT (W|w)ord* myfile
  105.  
  106. looks for "Word" or "word" at the beginning of a line only.  The match is
  107. normally case-sensitive -- although as we'll see later there is a keyword
  108. to switch this off.
  109.  
  110.  
  111.         MAT "#?(word|another||another word)#?" myfile
  112.  
  113. In this case Mat will look for "word" and "another" as before, but will NOT
  114. match a line containing the string "another word".  The double vertical bar
  115. is one of two ways of signifying negation.  Notice that quotes around the
  116. pattern are necessary now because of the imbedded space; I also used the
  117. alternative way of specifying <any-string> ("#?"), partly for demonstration
  118. and also because it may be a good idea to avoid the asterisk inside quotes
  119. as a general principle (it is itself a quoting character in certain
  120. circumstances).
  121.  
  122.  
  123.         MAT *^(word|another)^* "^1: ^0----^2" myfile
  124.  
  125. This time the pattern includes "slice marks" ("^"), so it is followed by a
  126. template indicating how the pieces are to be output. "^0" is the segment of
  127. the line matched by the part of the pattern before the first slice mark,
  128. "^1" is the segment between the two marks (i.e. "word" or "another",
  129. depending on which was matched), and "^2" is the rest of the line.  Thus,
  130. if the input line was
  131.  
  132.     "this line contains the word we are looking for"
  133.  
  134. the output would be
  135.  
  136.     "word: this line contains the ---- we are looking for"
  137.  
  138. (By the way, in this document "^" always means the caret character -- NEVER
  139. the control key!)
  140.  
  141.         MAT *(word|another)*^  "^F: ^O"  my#?  :T/#?.txt
  142.  
  143. Here Mat is doing the same search as in the first example, but we have
  144. included a slice mark to force the next argument to be a template.  This
  145. time, instead of just searching "myfile", we are looking at ALL files
  146. beginning with "my", and also all files in the directory :T that end in
  147. ".txt".  The "^F" code in the template outputs the current filename, and
  148. "^O" ("Oh" -- not "zero") outputs the whole Original line.
  149.  
  150.  
  151.         MAT >RAM:rn  FILES  "rename ^F as ^0_old^1"  #?^.c
  152.  
  153. In this final example we can see how to achieve my dream of renaming
  154. multiple files.  The output of Mat is directed to the temporary file
  155. "RAM:rn" so that we can then EXECUTE it as a command script to do the
  156. actual renaming.  The keyword "FILES" indicates that the search is to be
  157. for filenames, rather than the text they contain; in this syntactic form
  158. the keyword must be followed by a template to generate the output line.  In
  159. this form, we can put slice marks into the file pattern, so no separate
  160. main pattern is needed.  Within the template, "^F" refers to the original
  161. filename as before, and the new name will have "_old" inserted at the slice
  162. point (immediately before ".c", as specified in the file pattern).
  163.  
  164.  
  165.     If you got completely lost in the foregoing, please read the full
  166. manual that follows and try again.  First will be a description of the
  167. command line syntax for the various modes, then a discussion of pattern
  168. matching in general, followed by a description of the template format; the
  169. last section will detail the ways you can specify filename patterns.
  170.  
  171.                             %%%%%%%%%%%%%%
  172.  
  173.  
  174. Command Line Format
  175. ___________________
  176.  
  177.  
  178. Text-line Matching Mode:
  179.  
  180.     This mode searches text files for lines which match the supplied
  181.     pattern. The command format is:
  182.  
  183.         MAT <pattern> <file-specifier>...
  184.  
  185.     where <pattern> is any pattern that does not contain slice-marks. The
  186.     following arguments (at least one, but as many as you like) specify the
  187.     text file(s) you want to search for the pattern; they may be simple
  188.     file names (in the current directory), path names to files in another
  189.     directory, or patterns that specify sets of matching files.  See the
  190.     section on File Name Patterns for the full range of possibilities.
  191.  
  192.     Each line found in the text files searched that matches the pattern
  193.     will be sent to the standard output -- normally the screen, but it may
  194.     be sent to a file or device with the standard DOS redirection operator
  195.     (">").
  196.  
  197.     The file being searched will normally be a standard text file, with
  198.     each line terminated with a newline character, but non-text characters
  199.     cause no problem, and it is not fatal if newlines are missing.  If 256
  200.     characters are read before a newline is reached these will be treated
  201.     as a line, and the scan will resume with the character following; if
  202.     the string is output, though, it will have a newline added at the end,
  203.     unless the NOLINES keyword is used (see keywords section).
  204.  
  205.     By default, text searches are case-sensitive: "A" does not match "a".
  206.     You can ignore case in a search by including the NOCASE keyword in the
  207.     command line.  (Keywords are not shown in the basic command format to
  208.     avoid complexity and confusion.  Discussion of their general use has
  209.     its own section below.)
  210.  
  211.  
  212.  
  213.  
  214. Value returned to the CLI:
  215.  
  216.     When Mat returns to the CLI, it passes back a value of zero if it has
  217.     found at least one match.  If it has found no matches at all it returns
  218.     a "Warning" value of 5.  This happens in all modes, and can be tested
  219.     by a command script to see if the intended operation has been
  220.     successful.  If you should just want to know if a match exists, without
  221.     needing to see any output, you can simply redirect this to NIL:.
  222.  
  223.     If Mat encounters an error which prevents it from continuing, like an
  224.     incorrectly formed pattern, it will return at once with an error code
  225.     of 20.
  226.  
  227.  
  228. Slice'n Splice Mode:
  229.  
  230.     This mode searches text files for matching lines, but instead of simply
  231.     outputting matched lines, the lines found can be cut into pieces
  232.     according to "slice-marks" in the pattern; the output lines are built
  233.     from these and other items under the control of a template argument.
  234.  
  235.     The command format is:
  236.  
  237.         MAT <slice-pattern> <template> <file-specifier>...
  238.  
  239.     where <slice-pattern> is any pattern that contains at least one
  240.     slice-mark ("^").  It must be followed immediately by the template
  241.     argument that determines the format of each output line; these can be
  242.     generated for both matching and non-matching source lines.  File
  243.     specifiers are the same as in the previous mode.
  244.  
  245.     For matched lines the template can rearrange the sliced pieces of the
  246.     text and embed other constant text or such things as line number and
  247.     current file name.  For lines that don't match, the original line,
  248.     fixed text, line number and so on can be output.  Whatever its
  249.     contents, each output string always ends with a newline, unless the
  250.     NOLINES keyword is used (see below).  For details of the template
  251.     format see the later section on the subject.
  252.  
  253.     Don't forget that if you use a template you MUST include at least
  254.     one slice mark in the pattern you supply (even if you don't actually
  255.     want to cut the matched line up). Otherwise the program will get very
  256.     confused.
  257.  
  258.  
  259. Keywords:
  260.  
  261.     Variations on the above formats are controlled by keywords in the
  262.     command line.  In general, these may be placed either before the
  263.     pattern argument or intermixed with file specifiers; they must never be
  264.     put between a pattern and its template.  The exact effect may depend on
  265.     where on the command line they are placed; in many situations you could
  266.     have several interspersed along the line.  Mat always processes the
  267.     command arguments in sequence, from left to right (unlike the position
  268.     independent keywords of AmigaDOS commands).
  269.  
  270.     There are eleven possible keywords in this release of Mat (two of which
  271.     are just shorthand for others): NOCASE, CASE, FILES (or F), STRING,
  272.     JOIN (or J), FIRST, ALL, NOLINES and LINE.  They may be in upper or
  273.     lower case as convenient.  The keywords FILES (F), STRING, and JOIN
  274.     (J), set the mode of operation of the program; it is possible, but
  275.     probably not sensible, to change the mode in the middle of a command
  276.     line; there is no keyword to restore the default text search mode.  The
  277.     other keywords may be used in any mode where they are appropriate.
  278.  
  279.     NOCASE causes all subsequent searches to ignore the case of pattern and
  280.     text characters.  It can be put anywhere in the command line subject to
  281.     the above restrictions; file specifiers appearing before it will not be
  282.     affected.
  283.  
  284.     CASE cancels the effect of a previous NOCASE on the line; as this is
  285.     the default, you probably won't need it very often.
  286.  
  287.     FILES (or its shorthand alternative F) selects directory filename
  288.     search mode (see next section) rather than the default text file
  289.     search. It may change the command syntax: if it is the first argument,
  290.     it REPLACES the usual pattern argument, and MUST be followed by a
  291.     template.  You may also place it after a slice-pattern/template pair;
  292.     it is even permissible to put it between file specifiers if for some
  293.     odd reason you wished to mix the two types of searches, but this is not
  294.     recommended.
  295.  
  296.     STRING selects a mode where the pattern is matched against the literal
  297.     argument strings that follow on the command line.  Either a simple
  298.     pattern or sliced-pattern/template pair can be used.  This mode is
  299.     intended primarily for EXECUTE command scripts where you might want to
  300.     test that a supplied argument satisfied some pattern constraints, or
  301.     slice and rebuild it in some way.  You could also use it from the
  302.     keyboard to watch the effect of a particular pattern on various
  303.     strings.
  304.  
  305.     JOIN (or its shorthand J) needs neither pattern nor template (and both
  306.     MUST be omitted if the keyword is placed first).  It causes all the
  307.     files that match the specifier arguments to be sent in sequence to the
  308.     standard output.  No matching or other processing is done on the
  309.     contents (and these may be anything -- not necessarily text).
  310.  
  311.     FIRST is only appropriate in text matching modes.  It causes the search
  312.     of each file after it on the command line to terminate when the first
  313.     match is found. It is useful when you just want to determine which
  314.     files contain a pattern, rather than listing every occurrence.  It is
  315.     compatible with templates and other options.
  316.  
  317.     ALL reverses the effect of FIRST if you should need to do so within a
  318.     command line.  It will probably never be needed.
  319.  
  320.     NOLINES prevents the usual newline character being output after each
  321.     match.  All subsequent matches will be shown on the same line unless
  322.     the template dictates otherwise.  Don't forget that you will usually
  323.     want some sort of separator in the template, such as a space.  It can
  324.     be used in any mode.
  325.  
  326.     LINE reverses the effect of NOLINES if this has been given previously.
  327.     (Apologies for the plural/singular disparity, but it isn't quite the
  328.     inverse.)  It also inserts a newline into the output at that point; you
  329.     can use it just for this if you want an extra blank line between file
  330.     specifiers.
  331.  
  332.     If for some odd reason you should have to specify a pattern that is
  333.     exactly one of these keywords you can easily distinguish it by putting
  334.     parentheses around it or appending the null-string-match character "%".
  335.  
  336.  
  337. Filename Search Mode:
  338.  
  339.     This mode searches for filenames which match the supplied specifiers;
  340.     it does not examine the contents of the files.  A template is always
  341.     required to specify the form of the output.  There are two command
  342.     forms for this mode:
  343.  
  344.         MAT FILES <template> <file-specifier>...
  345.  
  346.         MAT <slice-pattern> <template> FILES <file-specifier>...
  347.  
  348.     In all cases, the abbreviation F can be used instead of FILES.
  349.  
  350.     In the first form, the FILES keyword replaces the usual pattern
  351.     argument; it must be followed by a template.  This simply finds all
  352.     files which match the supplied specifiers.  Slice marks may be included
  353.     in the filename part of a specifier (but not in the path part); if they
  354.     are present they will be recognized by the template, but they are
  355.     always optional. In this particular form, the template does not require
  356.     that slice-marks be present.  As in other filename searches, the match
  357.     never pays any attention to the case of either pattern or filename.
  358.  
  359.     In the second form, both a slice-pattern and a template must be
  360.     present.  Any filenames which match the specifiers will then be matched
  361.     against the main pattern and the appropriate action taken; any slice
  362.     marks in the specifiers are just ignored.  There are two notable
  363.     effects of this two-stage matching.  First, by default the final stage
  364.     is case-sensitive -- though the NOCASE keyword will reverse this.
  365.     Second, you can output lines for names that DON'T match in the second
  366.     stage, as well as ones that do.
  367.  
  368.  
  369.  
  370. Literal String Match Mode:
  371.  
  372.     This mode tests string arguments in the command line against the
  373.     pattern. The match can either be simple or sliced with a template.
  374.     Possible command forms are:
  375.  
  376.         MAT STRING <pattern> <string-argument>...
  377.  
  378.         MAT STRING <slice-pattern> <template> <string-argument>...
  379.  
  380.     The STRING keyword could also occur after the pattern or
  381.     pattern/template pair.  Putting it after one or more file specifiers
  382.     would change modes in the middle of the command; it is remotely
  383.     possible that this might be useful.
  384.  
  385.     Output from this mode is just as in the other modes, and as usual it
  386.     will return the value 5 to the CLI if all matches fail.
  387.  
  388.  
  389. File Concatenation Mode:
  390.  
  391.     With this mode, you can join multiple files into a single stream sent
  392.     to the standard output.  You can use it as a multiple "TYPE" command,
  393.     or -- if you redirect the output to a file -- as a "JOIN" command that
  394.     handles patterns.
  395.  
  396.         MAT JOIN <file-specifier>...
  397.  
  398.     You may use J as an abbreviation for JOIN if you wish.  No pattern or
  399.     template should be included.  The program pays no attention to the
  400.     contents of the files: they are simply treated as byte streams.
  401.  
  402.                                ========
  403.  
  404.  
  405. Pattern Matching
  406. ________________
  407.  
  408.  
  409.     The pattern matching algorithm used by Mat is an extension of the
  410. standard file pattern matching scheme used by AmigaDOS.  Many people may
  411. not appreciate how general and flexible the method is.  It is many times
  412. more capable than the simple "wild-card" matching available on most
  413. personal computers.  There are some things that the standard algorithm
  414. doesn't have which would often be useful, and I have done my best to supply
  415. some of these in this extended version.
  416.  
  417.     The discussion that follows may be a fuller exposition of how to use
  418. pattern matching than is available from other sources.  If you leave out
  419. references to the "universal-match" character "*", "negation matches", and
  420. "slicing", everything discussed applies just as well to standard AmigaDOS
  421. patterns, which can be used in commands like LIST, DELETE, and COPY.
  422.  
  423.     A pattern is a text string constructed from "plain characters" and
  424. "special characters".  It represents a set (possibly a large set) of text
  425. strings that will match it.  Remember that it always matches complete
  426. strings; this is not the same as a simple text search, where a match is
  427. signalled if the search string is found anywhere within the source text.
  428. The string being matched by the pattern is always "bounded" in some way,
  429. either because it stands alone -- like a file name -- or because, say, it
  430. is a complete line of text.  The newline character at the end is not
  431. usually available to the matching process.
  432.  
  433.     If a pattern argument in a command line contains spaces, it must of
  434. course be enclosed in quotes.  There is no way of including quotes in a
  435. pattern which is itself enclosed in quotes, unfortunately, (because of the
  436. way C handles argument strings).
  437.  
  438.     The syntax of the pattern structure is such that complex patterns can
  439. be built from simple ones.  Broadly speaking, patterns may be chained end
  440. to end so that successive segments of a complete target string may be
  441. matched by successive segments of the pattern.  In addition, each pattern
  442. segment can specify "alternatives": if any of these match, the whole
  443. segment matches.
  444.  
  445. Plain Characters:
  446.  
  447.     The simplest pattern is a string of plain characters.  This will only
  448.     match a target string consisting of exactly the same characters in the
  449.     same order, which is obviously of limited usefulness.  The only case
  450.     where you are likely to want this is when getting a particular file
  451.     name, and the program is smart enough to go directly to the file in
  452.     this case rather than doing a search.
  453.  
  454.  
  455. Special Characters:
  456.  
  457.     To build more general patterns we need the special characters. These do
  458.     not represent themselves (unless special action is taken): they are
  459.     instead structural elements that form the structure of the patterns we
  460.     desire. Using them we can build patterns -- or subpatterns -- that will
  461.     match, say, any single character, any five characters, any arbitrary
  462.     string, or a string that is one of several possible specific
  463.     alternatives. We can then put such subpatterns together to end up with
  464.     a complete pattern that will match all the various possibilities we are
  465.     looking for and no others.  The possibilities should become clearer as
  466.     we get to specific examples.
  467.  
  468.  
  469.     The seven special characters used in AmigaDOS file matching are:
  470.  
  471.             '  ?  |  (  )  #  and  %
  472.  
  473.     To these Mat adds two more:
  474.  
  475.             ~ and ^
  476.  
  477.     We'll look at them briefly in order, before we get into a fuller
  478.     exploration:
  479.  
  480.     " ' " makes the character following it into a plain character.
  481.     " ? " matches ANY single character.
  482.     " | " separates alternative patterns.
  483.     " ( " and " ) " enclose patterns used in building larger ones.
  484.     " # " causes a match to any number of repetitions of the pattern
  485.           it precedes.
  486.     " % " matches the null string when syntactically necessary.
  487.  
  488.     " ~ " is one way (of two) of sprecifying negation.
  489.     " ^ " slices a matched string into segments.
  490.  
  491.  
  492. Quoting Characters:
  493.  
  494.     The single quote (" ' ") is used to turn any special character
  495.     immediately following it into a plain character.  Thus to match against
  496.     an actual question mark in a target text you would include the pair
  497.     " '? " in the pattern.  And of course it can quote itself.
  498.  
  499.  
  500. Matching Any Character:
  501.  
  502.     The question mark matches ANY single character. Thus:
  503.  
  504.         ???
  505.  
  506.     matches "abc", "xyz", and so on, but not "ab" or "abcd".
  507.  
  508.  
  509. Matching Alternatives:
  510.  
  511.     The vertical bar (" | ") separates "alternatives".  If any of a set of
  512.     patterns separated by bars matches the target, the match is successful.
  513.     For example:
  514.  
  515.             abc|def|qwertyuiop
  516.  
  517.     would match any of those three strings, but no others.
  518.     The pattern
  519.  
  520.             abc|x?z
  521.  
  522.     would match "abc" or "x" and "z" separated by any single character.
  523.  
  524.  
  525. Building Patterns from Others:
  526.  
  527.     The left and right parentheses can be used to enclose a pattern that
  528.     you want to match as a unit when it is part of a larger pattern. As one
  529.     example we could look for any two characters followed by "abc" or "def"
  530.     with the pattern:
  531.  
  532.             ??(abc|def)
  533.  
  534.     Combine two or more patterns in sequence this way:
  535.  
  536.             (abc|def)(xxx|yyy)
  537.  
  538.     This will match "abcxxx", "abcyyy", "defxxx", and "defyyy".
  539.  
  540.     Patterns can be nested as far as you like with parentheses:
  541.  
  542.             a(bc|??(xx|yy))d
  543.  
  544.     will match "abcd", or any six-letter group beginning with "a" and
  545.     ending in "xxd" or "yyd".
  546.  
  547.     Redundant parentheses do no harm.  They may be useful to distinguish
  548.     patterns from other constructs.
  549.  
  550.  
  551. Pattern Repetition:
  552.  
  553.     The " # " character is always followed by a (sub)pattern. It will match
  554.     ANY number of (exact) repetitions of that pattern (INLUDING zero). The
  555.     pattern may be a single letter, but if it isn't it must be enclosed in
  556.     parentheses.  Thus:
  557.  
  558.             #(ab)
  559.  
  560.     matches "ab", "abababab", or simply an empty string.  It does not match
  561.     "ababa".
  562.  
  563.     Ther pattern to be repeated may be any legal pattern, including more
  564.     repetition constructs if you want:
  565.  
  566.             #(ab|?x|#(xy)z)
  567.  
  568.     will match such strings as "abab", "zxab", "qxxyxyxyxyzxyab", and so
  569.     on.  It will NOT match "abxy".
  570.  
  571.  
  572. Matching the Empty String:
  573.  
  574.     The " % " character is used where you have to specify an empty ("null")
  575.     string -- normally as one of a number of alternatives.  The
  576.     construction
  577.  
  578.             (|abc)
  579.  
  580.     is not legal; instead you must use:
  581.  
  582.             (%|abc)
  583.  
  584.     which will match either "abc" or the null string.
  585.  
  586.  
  587.  
  588. Negated Matching:
  589.  
  590.     Mat extends the basic pattern matching syntax by allowing you to
  591.     specify patterns that if matched will cause the overall match to fail.
  592.     If a negated segment is included in a pattern, and the target string
  593.     has ANY POSSIBLE match of the whole pattern that includes that segment,
  594.     the match cannot succeed.  There are restrictions on negation patterns
  595.     not shared by the structures we've talked about up to now; in
  596.     particular they can't be nested -- you can't negate a negation --
  597.     although they can be inserted at any level in the pattern.
  598.  
  599.     There are two ways of specifying negated patterns.  The first will
  600.     match ANY string UNLESS it exactly matches the pattern; it is
  601.     constructed by prefixing the pattern by the tilde (" ~ "):
  602.  
  603.             ab~(cd)e
  604.  
  605.     will not match "abcde", but will match any other string that begins
  606.     with "ab" and ends with "e", such as "abxxxe", "abe", "abce", etc..
  607.  
  608.     The second form is a "negated alternative", indicated by two adjacent
  609.     vertical bars (" || ").  This is used when, rather than matching ANY
  610.     string that is not the negated one, you have a set of patterns you want
  611.     to match UNLESS the negated part is also matched. Thus:
  612.  
  613.             a(b?d|?c?||bcd)
  614.  
  615.     will match four character strings such as "abxd", "accc", "abcx", as
  616.     long as the whole string is not "abcd".
  617.  
  618.     You can have more than one negated segment, as long as one does not
  619.     appear inside another.  Thus the following sort of thing is possible
  620.     (whether it's also useful though...?):
  621.  
  622.             a~bc~(de)(???||fgh||xyz)
  623.  
  624.     Remember that this will be forced to fail if there is any possible
  625.     match that includes a negated section, but on the other hand the tilde
  626.     construction matches any string that is not exactly the one specified.
  627.     Thus these will succeed:
  628.  
  629.             acxxx
  630.             abbbcddeabc
  631.             acdexy
  632.  
  633.     and these will fail:
  634.  
  635.             abcxxx
  636.             abbcdexxx
  637.             aczxsdefrgthcjxsxcxyz
  638.  
  639.  
  640. Slicing the Matched String:
  641.  
  642.     If it is appropriate to the function of the program, you can include
  643.     "slice marks" (the caret -- " ^ ") in your pattern to select out pieces
  644.     of the matched string that can be treated individually.  The way these
  645.     pieces are accessed is not the concern of the matching procedure; in
  646.     the case of Mat, the template argument provides ways of referencing
  647.     them.
  648.  
  649.     Once again there is a restriction on the use of this character that
  650.     does not apply to the others:  only the first four of these marks
  651.     encountered during a match will be recorded; any after this will be
  652.     ignored.  Note that this doesn't mean you can only include a maximum of
  653.     four marks; if they are inside alternatives that don't match any part
  654.     of the target string, the scan will never encounter them.  You should
  655.     be sure of what you are doing, though, if you don't want to be
  656.     surprised by the program's choices.  We'll return to this, and some
  657.     other points you should note about the behavior of slice marks, later.
  658.  
  659.     If there is more than one possible match of the pattern to the target,
  660.     the slice will be made at the earliest possible point.  Remember this
  661.     especially when you have repetitions in your pattern.
  662.  
  663.     Examples:
  664.  
  665.         The pattern         #?^x#?
  666.          will cut            abcdxyz
  667.          into                abcd xyz
  668.  
  669.          It will also cut    abcxxxx
  670.          into                abc xxxx
  671.  
  672.         The pattern         #?^x#?y^#?
  673.          will cut            abcxxxxyz
  674.          into                abc xxxxy z
  675.  
  676.         The pattern         #?^#x^#?
  677.          won't cut much of anything! (because "#x" also matches the null
  678.          string.)  The first two slices will simply always be empty, and
  679.          slice three will contain the whole string.
  680.  
  681.         The pattern         #?^(word|another)^#?
  682.          will cut            "here is another word for you"
  683.          into                "here is"  "another"  "word for you"
  684.          (using quotes in this case to mark off the slices).  Notice that
  685.          the cuts are made around "another" rather than "word" because the
  686.          earliest match is found.
  687.  
  688.     Slice marks within alternatives can be used, as noted above, but are
  689.     tricky. Because of the way the marks are recorded internally, if two
  690.     different alternatives containing them match, both marks will be
  691.     reported but the position of one of them will be wrong (probably at the
  692.     beginning of the string).  So it is best to keep the slice marks
  693.     outside of any alternation constructions (as shown in the last example
  694.     above).
  695.  
  696.  
  697.  
  698. Templates
  699. _________
  700.  
  701.     The Templates Mat uses to generate output lines are basically simple
  702. text strings with "splice-markers" that indicate where the pieces of the
  703. matched string and other items are to be inserted.  The text segments if a
  704. template can be anything you want (except a newline -- there is a marker
  705. for this).  A special marker can be used to divide the template string into
  706. "success" and "fail" halves; the "success" part controls the format of
  707. output lines for matches, while the "fail" part will be output for each
  708. input string that doesn't match. Output strings are always terminated with
  709. a newline.
  710.  
  711.     Each marker is a character pair: the caret (" ^ ") followed by a
  712. selector character.  Slices from the matched string are numbered -- "^0" to
  713. "^4" .  Other items have identifying letters, such as "^N" for line number;
  714. the case of these letters is important (all are currently upper case
  715. because you are already holding down the shift key for the caret). The
  716. success/fail divider uses the vertical bar: "^|".
  717.  
  718. Not all selectors are valid under all conditions.  For example you can't
  719. use slices in the "fail" section of a template because -- obviously --
  720. there aren't any.  Line numbers, on the other hand, are only appropriate in
  721. text matching, not in file name matching mode.  If you use a selector that
  722. is not valid it is simply skipped over.  Of course you can use any selector
  723. more than once within a template.
  724.  
  725.     If a template argument in a command line contains spaces, it must of
  726. course be enclosed in quotes.  As with a pattern, you can't include quotes
  727. in a template which is itself enclosed in quotes: use the "^Q" selector
  728. instead.
  729.  
  730.  
  731. Slice Selectors:
  732.  
  733.     As four slice marks are allowed in a pattern, there can be a maximum of
  734.     five slices of the matched string.  These are selected by "^0" for the
  735.     piece from the beginning of the string to the first mark, "^1" for the
  736.     piece between the first and second, up to "^4" for the remainder of the
  737.     string beyond the fourth mark.  If there are fewer than four slice
  738.     marks, the slice associated with the final existing mark extends to the
  739.     end of the string, and all higher-number pieces are empty.  Thus if
  740.     there are only two marks, "^2" covers the remainder of the string, and
  741.     "^3" and "^4" are empty.
  742.  
  743.     For instance, if we use this pattern, with two slice marks:
  744.  
  745.             #?^word ^#?
  746.  
  747.     and this template -- which will omit slice 1:
  748.  
  749.             ^0^2
  750.  
  751.     to match and rearrange the string:
  752.  
  753.             "this word will be missing"
  754.  
  755.     we will end up with:
  756.  
  757.             "this will be missing"
  758.  
  759.  
  760. Line Number Selector:
  761.  
  762.     The selector characters "^N" placed in a template string will insert
  763.     the current line Number within the file being scanned at that point in
  764.     the output string.  The number is always five digits, with leading
  765.     zeros visible.  At the moment there is no option to suppress leading
  766.     zeros, partly because it makes it easier to line up columns and partly
  767.     because I wanted fast code there [and don't forget the laziness
  768.     syndrome, Peter...].  It can be used in both "success" and "fail"
  769.     portions of a template.
  770.  
  771.     So the pattern                      #?^(word|another)^#?
  772.      and template                       ^N: ^1
  773.      would generate something like      00234: another
  774.  
  775.  
  776. Index Number Selector:
  777.  
  778.     The pair "^I" inserts an Index number representing a count of matches
  779.     so far. The count is kept from the beginning of the program, and is not
  780.     reset with a new file.  It also works in file name matching mode.  You
  781.     may use it in the "fail" section of a template, but remember it will
  782.     indicate the number of matches, not lines output.  The format is the
  783.     same as "^N".
  784.  
  785.  
  786. Original String Selector:
  787.  
  788.     The pair "^O" ("Oh", not "zero" -- I probably should have chosen a
  789.     better one...) represents the unsliced Original string.  It can be used
  790.     in both the "success" and "fail" parts of a template.  Thus, to simply
  791.     put a line number in front of each matched line, you could use the
  792.     template:
  793.  
  794.             ^N: ^O
  795.  
  796.     In File Matching mode, this selector is the same as "^F" (below).
  797.  
  798.  
  799. Line Break Selector:
  800.  
  801.     The pair "^B" Breaks the output line at that point with a newline
  802.     character.  For instance, to output line number and slice-1 on one
  803.     line, followed by the original string on a new line, use:
  804.  
  805.             ^N: ^1^B^O
  806.  
  807.  
  808. Quote Mark Selector:
  809.  
  810.     It is not usually possible to embed quote marks in template strings
  811.     directly, so you can use the selector "^Q" to make them appear at that
  812.     point in the output line.
  813.  
  814.             ^0 ^Q^1^Q ^2
  815.  
  816.  
  817. File Name Selector:
  818.  
  819.     "^F" selects the local name of the current File (i.e without any
  820.     directory prefix), in both text and file name matching modes.
  821.  
  822.     For example, if you have a filename specifier argument (see later)
  823.  
  824.             :work#?/#?.txt
  825.  
  826.     which has found the file
  827.  
  828.             Work Disk:work_1/sample.txt
  829.  
  830.     the "^F" selector will insert
  831.  
  832.             sample.txt
  833.  
  834.  
  835. Directory Path Selector:
  836.  
  837.     "^D" in a template will insert the path to the Directory of the current
  838.     file, as seen by Mat, based on the specifier argument it is using.
  839.     The exact form of this string depends on the way you have formed the
  840.     directory part of the file specifier argument.  It does NOT always
  841.     contain a complete path from device to file.  If you are just assuming
  842.     the current directory the string will be empty. If the file is in a
  843.     different directory it will show the chain of directories it has used
  844.     to reach it, using the full directory names it has found.
  845.  
  846.     Some specific examples:
  847.  
  848.     If we used the file specifier as in the previous section, and found the
  849.     same file:
  850.  
  851.             Work Disk:work_1/sample.txt
  852.  
  853.     ^D would insert
  854.  
  855.             Work Disk:work_1
  856.  
  857.     On the other hand, if the specifier was
  858.  
  859.             work#?/#?.txt
  860.  
  861.     ^D would give
  862.  
  863.             work_1
  864.  
  865.     You should especially note that if you did not use a device specifier
  866.     (":") in the first section of your specifier, yet the first directory
  867.     in the chain IS in fact a root directory, you will see a slash "/"
  868.     separator rather than the colon in the string supplied by ^D. Thus if
  869.     your specifier happened to be
  870.  
  871.             /work#?/#?.txt
  872.  
  873.     the Directory path would be shown as
  874.  
  875.             Work Disk/work_1
  876.  
  877.  
  878. Failure Template Marker:
  879.  
  880.     A simple template is only applied to strings which have been matched,
  881.     and nothing is output when there isn't a match.  You can split the
  882.     template, however, into two subsections with the special success/fail
  883.     division marker "^|".  The section preceding this mark is applied for a
  884.     successful match just like a simple template; the section following it
  885.     is used if the match fails. In the "fail" section, any selectors
  886.     desired can be used, except the five slices "^0" - "^4".
  887.  
  888.     A simple use would be to output all lines, whether or not they matched,
  889.     but mark or rearrange the matched lines in some way.  For example the
  890.     following would output them all but put a marker and index number on
  891.     each matched line (and corresponding blanks before an umatched one):
  892.  
  893.             MATCH[^I]> ^O^|             ^O
  894.  
  895.  
  896.  
  897. File Specifiers
  898. _______________
  899.  
  900.     The arguments in the command line you supply to specify the files that
  901. Mat will examine are really just like those you might give to any AmigaDOS
  902. command, but there are one or two extra features.
  903.  
  904.     For text file searches you will probably most often want to specify a
  905. single file.  You do this in the usual way with either the local name of a
  906. file in the same directory, or a path name that includes the chain of
  907. directories needed to reach that file in another.  In place of the simple
  908. file name, you can use a pattern to match a group of files in the same
  909. directory.  Unlike other AmigaDOS commands this pattern can employ the
  910. extended matching features described above ("*", "~", and "||"). Slice
  911. marks can also be used where they are appropriate (see below).
  912.  
  913.     You can also use patterns in the directory part of the specification,
  914. in just the same way as in the filename part.  (Did you know that you can
  915. also do this in most AmigaDOS commands supporting patterns, such as
  916. DELETE?)  All the directories matching that specification will be searched
  917. in turn. However, you cannot split a pattern across directories -- in other
  918. words, a pattern must not include a device or directory separator (":" or
  919. "/"). This means that a given pattern can only match directory names at a
  920. certain "level" in the file hierarchy of the disk.  Also you cannot use a
  921. pattern in a device specifier -- these must be simple names.  To search
  922. more than one level, or more than one device, you must have more specifier
  923. arguments.
  924.  
  925. In File Name Search mode, if you don't supply any other pattern, you may
  926. put slice marks in the file name portion of the specifier.  You cannot
  927. place them in the directory part.  Except in this particular situation,
  928. with no main pattern present, slices in the filename will be ignored.
  929.  
  930.  
  931. Examples:
  932.  
  933.     These are valid file specifiers:
  934.  
  935.             myfile.txt
  936.             my#?file(.txt|_bak)
  937.             df1:work/myfile
  938.             :work/myfile
  939.             /work/myfile
  940.             :(work|old)/my^#?
  941.  
  942.     These are not:
  943.  
  944.             df(0|1):#?/#?           -- pattern in device part
  945.             df1:/#(work/)myfile     -- pattern includes directory separator
  946.             :w^#?/my^#?             -- slice mark in directory part
  947.  
  948.  
  949.  
  950.  
  951. The Real World
  952. ______________
  953.  
  954.  
  955.     Even before it had reached its current form, this program was put to
  956. good use a couple of times.  One case needed the text match facility, the
  957. other the filename match.
  958.  
  959.     I had a documentation file for another project, written in "proff" text
  960. formatter format, and I wanted to convert it to "troff" for typesetting on
  961. a Un*x system.  I ran it through Mat several times, first simply to locate
  962. all the formatter commands -- a simple job because they are all lines
  963. beginning with a period --, and then to actually rewrite some of the
  964. commands in troff form, slicing up the original commands and reusing the
  965. appropriate parts.  I was even able to generate some added commands to
  966. create indented paragraphs and so on.
  967.  
  968.     The other application also involved text files, this time an article I
  969. had written for a newsletter.  The disk I passed on to the magazine's
  970. editor already had two versions of the text, and he had to cut it further
  971. into pieces for the layout program.  So when it came time to put Part 2 on
  972. the same disk, I had all these old files -- which I didn't want to throw
  973. out -- cluttering the top level of the disk.  Of course I could have simply
  974. copied them to a new directory and then deleted the originals, but for one
  975. thing that would change their date.  Better to rename them all to be in a
  976. new directory, except that without Mat I would have had to do each one
  977. individually.  The commands I used were something like:
  978.  
  979.         makedir old
  980.         mat >ram:rn f "rename ^F as old/^0_Part.1_^1" article^#?
  981.         execute ram:rn
  982.  
  983. (except that I was using Sili(Con:), so I could type simply "ram:rn",
  984. rather than "execute ram:rn"...).
  985.  
  986.     As another example, I have a little command script file I call "ref",
  987. which searches for the pattern given as its first argument in the files
  988. corresponding to the following ones, and prints out matching lines with the
  989. match itself highlighted:
  990.  
  991. .K PAT,FILE1,FILE2,FILE3
  992. Mat "#?^<PAT>^#?" "^0<esc>[1;33;40m^1<esc>[0;31;40m^2" <FILE1> <FILE2>
  993. <FILE3>
  994.  
  995. Notice that the pattern argument you supply is automatically surrounded
  996. with universal matches and slice marks.  If you aren't familiar with the
  997. strange strings in the template, these are ANSI control sequences
  998. recognized by the console device to change text color; <esc> is the ESCape
  999. character. To create a script file like this of course you'll need an
  1000. editor such as EMACS that can handle <esc> as a character.
  1001.  
  1002.     Here is a short script that is convenient for sending multiple files to
  1003. your printer; it is a little better than PRINTFILES (the 1.2 Extras
  1004. command) in that it allows filename patterns (and is configured to run
  1005. automatically in the background):
  1006.  
  1007.      .K f1,f2,f3,f4,f5
  1008.      .bra {
  1009.      .ket }
  1010.      ;*** caution -- the next line is too long for most printers! ***
  1011.      run mat >t:_pr f "cd ^Q^D^Q^Btype >prt: ^F^Becho >prt: ^Q ^Q" {f1} {f2} {f3} {f4} {f5} +
  1012.       execute t:_pr +
  1013.       delete t:_pr
  1014.  
  1015. It also shows up some of the deficiencies of the current version of Mat
  1016. (as elaborated in the next section): for example it is better to CD to the
  1017. "^D" directory because it is not always possible to concatenate directory
  1018. and filename (if "^D" is a device for instance); also if you aren't careful
  1019. in specifying pathnames, "^D" may not be a proper directory identification
  1020. string -- see the discussion on "^D" in the Template section.
  1021.  
  1022.  
  1023. Deficiencies and Prospects
  1024. __________________________
  1025.  
  1026.     Mat is obviously missing some things in its current incarnation.
  1027. When and whether they get added will depend both on my own further needs
  1028. and moods and on your feedback.  (I'd be delighted with monetary
  1029. contributions, but this is for you to use and distribute anyway...)
  1030.  
  1031.     The matching algorithm, even though extended over the original, is
  1032. in need of a couple more options.  Un*x "regular expresssions" have a way
  1033. of specifying sets and ranges of characters, and while I don't think Mat
  1034. needs sets -- alternation handles this reasonably well -- some way of
  1035. specifying ranges would be a big advantage.  I have often wanted to search
  1036. for "any letter", say.  I think the best way to implement this would be to
  1037. define specific "range selectors" such as "any letter", "any digit", "any
  1038. upper case", and so on, probably using a convention like "\a".
  1039.  
  1040.     The selectors available for template use could also be expanded.  In
  1041. particular there is an obvious need for a true directory path, rather than
  1042. the one that Mat currently assembles from the individual directory names it
  1043. has traversed.  Any other suggestions?
  1044.  
  1045.     Keywords are easy to add, so... Oh, you noticed -- yes, well their
  1046. number did grow rather rapidly, but there are still a few I would like to
  1047. add.  HEAD and TAIL would be followed by template-type arguments that would
  1048. generate output at the beginning and end respectively of each file.  TITLE
  1049. would do the same thing wherever it occurred in the command line.  These
  1050. would be especially useful in NOLINES mode.
  1051.  
  1052.     The matching algorithm is slower than I would like.  Rewriting it in
  1053. assembly would doubtless help, but there is also a need for a "quick match"
  1054. feature for simpler patterns closer to those that SEARCH can handle.
  1055.  
  1056.     I have other vaguer notions, too, such as how to request multiple
  1057. levels of directories in a specifier, but I'll have to think about them
  1058. awhile.
  1059.  
  1060.  
  1061. Distribution and Copyrights
  1062. ___________________________
  1063.  
  1064.  
  1065.     Mat itself and this manual are copyright, but may be freely distributed
  1066. without charge.  Commercial use is prohibited without the express written
  1067. permission of the author.
  1068.  
  1069.     The matching algorithm code is public domain.  It is an extension of an
  1070. algorithm in an original article by Martin Richards in "Software Practice
  1071. and Experience" 1979.  The source is in fairly generic 'C'; it has only
  1072. been compiled under Lattice 3.10, but should be readily transportable.
  1073.  
  1074.  
  1075. Remarks and Suggestions to:
  1076.                                         Peter Goodeve
  1077.                                         3012 Deakin Street #D
  1078.                                         Berkeley, Calif. 94705
  1079.  
  1080.                             %%%%%%%%%%%%
  1081.  
  1082.