UNIX tips

Last updated on Thu Jun 10 00:40:33 CEST 2021.

This page is a collection of simple tips for working with and on UNIX that don't deserve a page of their own.

sh: Operate on argv

The following sh snippet will process every command-line argument with COMMAND. It successfully retains the structure of $@ and handles whitespace correctly.

i=0
while [ $((++i)) -le $# ]; do
	a=`COMMAND $1`
	shift
	set -- "$@" "$a"
done

vi: Useful search and replace

The quickest way to move the cursor to a specific place in the document is to use the search commands, // and ??. Remember that // and ?? can be used as motions, too: d/x^M deletes everything until the next occurrence of "x".

However, you often want to delete everything before "x" as well as "x" itself. While vi offers no built-in command for this, the following mapping often works well enough [1]:

map ^M :s///^M

That maps the Return key to delete the first occurrence of the previously searched phrase on the current line. It works as long as "x" is sufficiently unique.

Fortunately, you're likely to notice if it deletes the wrong thing, as (at least my implementation of) vi will move you to the beginning of the line if it deletes anything before the cursor.

If you really want a command that reliably deletes the found phrase, and not the same phrase earlier in the same line, the following should do the trick:

map ^M i^M^[:s///^Mk:j^Ml

Note that it doesn't work if you move after your search. Another drawback is that it requires multiple undos to undo.

grep: Find function definitions

Well-formatted C code writes function definitions like this:

int
main(...)
{
	...
}

This makes it easy to find function definitions with regular expressions. The following command finds the definition of the parse function, searching all C source files in the current directory:

$ grep -n ^parse\( *.c
util.c:342:parse(char *s)

(It would be great if the shell would treat an opening parenthesis at the end of a word as a literal character.)

To make this pattern even more useful, I use a script called dwim [2] to translate the results (util.c:342) to the corresponding vi invocation:

$ dwim util.c:342 # runs "vi +342 util.c"

References

  1. Character combinations beginning with a caret (^) denote control characters. These can be entered into vi by prefixing the control sequence with ^V.
  2. http://git.ankarstrom.se/dwim/