2007/05/30

piping text lines / "Here Documents"

Many ways to do this. Here's two:

    prog << EOF
    line 1
    line 2
    ...
    line N
    EOF


or

    (echo "line 1"
    echo "line 2"
    ...
    echo "line N") | prog


The "<< EOF" syntax creates what is usually called a "here is" document.
The shell takes all of the lines up to (but not including) the line that
begins "EOF" (in column 1), writes all those lines to a temporary file,
and then feeds that file as standard input to "prog", just as in your
original example (except that the shell is doing the work for you). When
"prog" has finished executing, the temporary file is deleted. You can
replace "EOF" by any string that does not appear in the input; the "<<" is
the important part.

Another version of it uses the syntax "<<-EOF". The effect of the "-" is
to allow the terminating EOF to be on a line that has leading white space
on it; it is an instruction to ignore any leading white space in the data
(all of the data, not just the EOF line).

It's usually better to use the facilities provided by the shell rather
than writing out the equivalent code using some other technique. Less code
usually leads to fewer bugs and easier maintenance, because it is
hopefully more readable that way. It's probably a bit more efficient to
use the "<< XXX" method, but not by a lot in this instance (unless you're
doing it very many times).

Steve Thompson

#-----------------------------------------------------
#-----------------------------------------------------


    % (echo "juan"; echo "1"; echo "alba") | sort
    1
    alba
    juan

    % sort << XXXX
    > 5
    > 2
    > 5
    > 1
    > b
    > c
    > XXXX
    1
    2
    5
    5
    b
    c


http://www.tdp.org

"Advanced Bash-Scripting Guide"
And check the chapter about "Here Documents".
Michael Heiming

#-----------------------------------------------------
#-----------------------------------------------------


    {
    echo "line 1"
    echo "line 2"
    ...
    echo "line N"

    } | prog


Or:


    printf "%s\n" "line 1" \
    "line 2" ... \
    "line N" | prog


Chris F.A. Johnson

#-----------------------------------------------------
#-----------------------------------------------------

One person already gave an example that uses the "<< EOF" syntax,
but if you really need to group commands' output together into
a pipe, and you have to commands (and not just interpolated strings),
you can do this:


    {
    echo "line 1"
    echo "line 2"
    echo "line 3"
    } | prog


Personally I like this since it is more flexible. You can chain
them:


    { echo 1; echo 2; } | { read x; read y; echo "$x / $y"; } | bc -l


Or nest them:


    {
    echo 1
    {
    echo 2
    echo 3
    } | sed -e 's/$/x/'
    echo 4
    } | sed -e 's/$/y/'


Also, in some cases, a better solution might be to use a function.

- Logan

No comments: