<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter 10. Commands in a Pipe</title><meta name="generator" content="DocBook XSL Stylesheets V1.71.1"><link rel="start" href="index.html" title="A-A-P Recipe Executive"><link rel="up" href="tutorial.html" title="Part I. Tutorial"><link rel="prev" href="tutor-include.html" title="Chapter 9. More Than One Recipe"><link rel="next" href="tutor-port.html" title="Chapter 11. A Ported Application"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><table width="100%" id="navtable"><tbody><tr><td align="left" class="left" width="33%"><b><a href="http://www.a-a-p.org">A-A-P home page</a></b></td><td align="center" class="center" width="34%"><b><a href="index.html">A-A-P Recipe Executive</a></b></td><td align="right" class="right" width="33%"></td></tr><tr><td align="left" class="left"><a accesskey="p" href="tutor-include.html">Prev</a></td><td align="center" class="center">Tutorial</td><td align="right" class="right"><a accesskey="n" href="tutor-port.html">Next</a></td></tr></tbody></table><hr><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="tutor-pipe"></a>Chapter 10. Commands in a Pipe</h2></div></div></div><p> A selection of commands can be connected together with a pipe. This means the output of one command is the input for the next command. It is useful for filtering text from a variable or file and writing the result in a variable or file. </p><h2><a name="id2631646"></a>Changing a timestamp</h2><p> This example shows how you can change the timestamp in a file. It is done in-place. </p><pre class="programlisting"> all: :print Setting date in foobar.txt. :cat foobar.txt | :eval re.sub('Last Change: .*\n', 'Last Change: ' + DATESTR + '\n', stdin) >! foobar.txt </pre><p> Lets see how this works: </p><div class="literallayout"><p> % <strong class="userinput"><code>cat foobar.txt</code></strong><br> This is example text for the A-A-P tutorial.<br> Last Change: 2002 Feb 29<br> The useful contents would start here.<br> % <strong class="userinput"><code>aap</code></strong><br> Setting date in foobar.txt.<br> % <strong class="userinput"><code>cat foobar.txt</code></strong><br> This is example text for the A-A-P tutorial.<br> Last Change: 2002 Oct 21<br> The useful contents would start here.<br> %<br> </p></div><p> The last command in the example consists of three parts. First comes the <code class="computeroutput">:cat</code> command. It reads the "foobar.txt" file and passes it throught the pipe to the next command. "cat" is short for "concatenate". This is one of the good-old Unix commands that actually does much more than the name suggests. In this example nothing is concatenated. Below you will see examples where it does. </p><p> The second part of the example is the <code class="computeroutput">:eval</code> command. This is used to read the text coming in through the pipe and modify it with a Python expression. In this case the expression is a "re.sub()" function call. This Python function takes three arguments: A pattern, a replacement string and the text to operate on. All occurences of the pattern in the text are changed to the replacement string. The pattern "Last Change: .*\n" matches a line with the date that was inserted previously. The replacement string contains <code class="literal">DATESTR</code>, which is an <span class="application">Aap</span> variable that contains today's date as a string, e.g., "2002 Oct 19". The text to operate on is <code class="literal">stdin</code>. This is the variable that holds the text that is coming in through the pipe. </p><p> The third and last part <code class="computeroutput">>! foobar.txt</code> redirects the output of the <code class="computeroutput">:eval</code> command back to the file "foobar.txt". Using just ">" would cause an error, since the file already exists. </p><p> Note that in a Unix shell command this pipe would not work: The "foobar.txt" would be overwritten before it was read. In <span class="application">Aap</span> this does not happen, the commands in the pipe are executed one by one. That makes it easier to use, but it does mean the text is kept in memory. Don't use pipes for a file that is bigger than half the memory you have available. </p><p> Changing a file in-place has the disadvantage that the normal dependencies don't work, since there is no separate source and target file. Often it is better to use a file "foobar.txt.in" as source, change it like in the example above and write it as a new file. The recipe would be: </p><pre class="programlisting"> foobar.txt: foobar.txt.in :print Setting date in $target. :cat $source | :eval re.sub('Last Change: .*\n', 'Last Change: ' + DATESTR + '\n', stdin) >! $target </pre><h2><a name="id2633390"></a>Creating a file from pieces</h2><p> Sometimes you need to generate a file from several pieces. Here is an example that concatenates two files and puts a generated text line in between. </p><pre class="programlisting"> manual.html: body.html footer.html @import time :eval time.strftime("%A %d %B %Y", time.localtime(time.time())) | :print $(lt)BR$(gt)Last updated: $stdin$BR | :cat body.html - footer.html >! $target </pre><p> There are quite a few items here that need to be explained. First of all, the "@import time" line. This is a Python command to load the "time" module. So far we used modules that <span class="application">Aap</span> has already loaded for you. This one isn't, and since we use the "time" module in the next <code class="computeroutput">:eval</code> command it needs to be loaded explicitly. </p><p> The Python function "strftime()" formats the date and time in a specified format. See the Python documentation for the details. In this case the resulting string looks like "Monday 21 October 2002". </p><p> The output of the <code class="computeroutput">:eval</code> command is piped into a <code class="computeroutput">:print</code> command. The variable <code class="literal">stdin</code> contains the output of the previous command. Note that "$(lt)" is used instead of "$lt". The meaning is exactly the same: the value of the <code class="literal">lt</code> variable. Without the extra parenthesis it would read "$ltBR", which would be the value of the "ltBR" variable. </p><p> The resulting text is: </p><div class="literallayout"><p> <BR>Last updated: Monday 21 October 2002\n<br> </p></div><p> Note that the first "BR" is the HTML code for a line break, while the "$Br" at the end is the <span class="application">Aap</span> variable that contains a line break (here displayed as "\n"). </p><p> Finally, the <code class="computeroutput">:cat</code> command concatenates the file "body.html", the output of the <code class="computeroutput">:print</code> command and the file "footer.html". Thus the "-" stands for where the pipe input is used. The result is redirected to <code class="literal">target</code>, which is "manual.html". </p><h2><a name="id2633554"></a>Pipe output in a variable</h2><p> The generated date in the previous example could be used elsewhere in the recipe. Since we don't want to repeat a complicated expression the result of the <code class="computeroutput">:eval</code> command should be redirected to a variable, like this: </p><pre class="programlisting"> @import time :eval time.strftime("%A %d %B %Y", time.localtime(time.time())) | :assign Datestamp manual.html: body.html footer.html :print $(lt)BR$(gt)Last updated: $Datestamp$Br | :cat body.html - footer.html >! $target </pre><p> The <code class="computeroutput">:assign</code> command takes the input from the pipe and puts it in the variable mentioned as its argument, which is "Datestamp" here. Actually, the same can be done with a normal assignment and a Python expression in backticks, but we intentionally wanted to show using a pipe here. </p><h2><a name="id2633580"></a>Creating a file from scratch</h2><p> It is also possible to completely generate a file from scratch. Here is an example that generates a C header file: </p><pre class="programlisting"> 1 :include config.aap 2 pathdef.c: config.aap 3 :print Creating $target 4 :print >! $target /* pathdef.c */ 5 :print >> $target /* This file is automatically created by main.aap */ 6 :print >> $target /* DO NOT EDIT! Change main.aap only. */ 7 :print >> $target $#include "vim.h" 8 :print >> $target char_u *default_vim_dir = (char_u *)"$VIMRCLOC"; 9 :print >> $target char_u *all_cflags = (char_u *)"$CC -c -I$srcdir $CFLAGS"; </pre><p> The first <code class="computeroutput">:print</code> command displays a message, so that it's clear "pathdef.c" is being generated. The next line contains ">!" to overwrite an existing file. It doesn't matter if the file already existed or not, it now only contains the line "/* pathdef.c */". The third and following lines contain ">>". This will cause each line to be appended to "pathdef.c". </p><p> In the example the <code class="literal">VIMRCLOC</code> and <code class="literal">srcdir</code> variables are defined in the recipe "config.aap". That is why this file is used as a source in the dependency. Also note the use of "$#" in line 7. Since "#" normally starts a comment it cannot be used directly here. "$#" is a special item that results in a "#" in the <code class="computeroutput">:print</code> output. This is the resulting file: </p><div class="literallayout"><p> /* pathdef.c */<br> /* This file is automatically created by main.aap */<br> /* DO NOT EDIT! Change main.aap only. */<br> #include "vim.h"<br> char_u *default_vim_dir = (char_u *)"/usr/local/share/vim61";<br> char_u *all_cflags = (char_u *)"cc -c -I. -g -O2";<br> </p></div><p> The list of ">>" redirections is quite verbose. Fortunately there is a shorter way: </p><pre class="programlisting"> 1 :include config.aap 2 pathdef.c: config.aap 3 :print Creating $target 4 text << EOF 5 /* pathdef.c */ 6 /* This file is automatically created by main.aap */ 7 /* DO NOT EDIT! Change main.aap only. */ 8 $#include "vim.h" 9 char_u *default_vim_dir = (char_u *)"$VIMRCLOC"; 10 char_u *all_cflags = (char_u *)"$CC -c -I$srcdir $CFLAGS"; 11 EOF 12 :print $text >! $target </pre><p> In line 4 "text << EOF" is used. This is called a block assignment. The following lines, up to the matching "EOF" line, are assigned to the variable <code class="literal">text</code>. You can use something else than "EOF" if you want to. It must be a word that does not appear inside of the text as a line on its own. White space before and after the word is ignored. </p><p> The indent of the text in the block assignment is removed. The indent of the first line is used, the same amount of indent is removed from the following lines. Thus if the second line has two more spaces worth of indent than the first line, it will have an indent of two spaces in the result. Half a tab is replace with four spaces when necessary (a tab always counts for up to eight spaces). </p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="tutor-include.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="tutorial.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="tutor-port.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 9. More Than One Recipe </td><td width="20%" align="center"><a accesskey="h" href="index.html"> Contents</a></td><td width="40%" align="right" valign="top"> Chapter 11. A Ported Application</td></tr></table></div></body></html>