Tuesday, October 30, 2007

Tricks on handling multiple line inputs and outputs

There are some of the trivial bag of tricks that I don't normally take notice, which does often comes back to bother me. I just have to trip on Finagle's Law whenever I forget these tricks after long disuse. Things like handling multi-line inputs and outputs seems to fit into that category, so here's all I can recall form my own reference:

Printing multiple line outputs with a single echo command

The special escape for newline in bash is $'\n'. Here's an example how it's being used:

% echo "Hello$'\n'World"

Other non-printable characters can be similarly escaped this way (e.g. The NUL terminator represented by $'\0').

Reading multi-line inputs from stdin

This is achieved by using the << operator:

% cat <<TEST
> This is a test
> Hello World
This is a test
Hello World

Reading multi-lines of a file into a single variable

Because spaces are treated as field separators in bash, and it won't try to read past the first separator, you need to force the shell to treat nothing as a separator, by modifying the IFS (Input Field Separator):

OLDIFS=$IFS IFS= var=($(< filename.txt)) IFS=$OLDIFS

This above example assumes that you have a file called filename.txt, and at the end of the operation, the entire contents of the file is stored in the var variable.

Matching multiple lines using grep

When searching for two or more consecutive words within a sentence on a text file (or HTML), sometimes it is possible that the words are span across multiple lines, hence making typical word search, barring from using a script, difficult. One of the neat tricks to accomplish this without using any script, is through GNU grep's -P flag.

Assuming that you have a file called test.txt that spans two or more lines:

I like to say a nice warm "Hello
World" to all of you out there!

To search for the consecutive words "Hello World":

grep -P "Hello\WWorld" test.txt

Curiously, it does not seem to work on Gentoo/Ubuntu linux's version of grep but works only on my old RedHat distro only. Maybe it's something that has been phased out.

Splitting inputs into multiple lines

The easiest way to split things on the command line is to use the sed

% echo "Hello World" | sed -e 's/ /\n/'

If you want to do this within vim, it is a little bit less straightforward but still doable:

:s/ /<CTRL-V><ENTER>/

Replace the items in the angled-braces with the actual keystroke itself. The screen the output actually looks like:

:s/ /^M/

So don't be concerned by the visual difference.


Post a Comment