dd-ex is a simple line editor completely written as a shell
script. Yup, you read it right - a shell script. To make things more
interesting, we use only two external commands: dd and
rm; the latter is not necessary, but it is nice to clean
up temporary files.
dd only. This is
obviously true, as you can use it to copy portions on files. You can
see the section "How?" for an example.
The challenge, of course, is to do this automatically. Although
we can do everything using dd, it is not obvious that the
Bourne shell is powerful enough for that. So I had to try and see -
and now I can say that it is possible.
dd if=your_file bs=1 count=372 of=/tmp/file.beginning dd if=your_file bs=1 skip=377 of=/tmp/file.end dd of=/tmp/file.replacement bs=1 count=8 <<EOF hyewrfub EOF ( dd if=/tmp/file.beginning; dd if=/file.replacement dd if=file.end ) | \ dd of=your_fileThis might just need some explanation. The first line copies the initial 372 bytes of your_file to /tmp/file.beginning; the next line copies the bytes after 377 to /tmp/file.end; finally, we copy the new string to /tmp/file.replacement. If we just used:
dd of=/tmp/file.replacement bs=1 <<EOF hyewrfub EOFwe would get an extra newline at the end of the string - we add "count=8" to copy only the first 8 bytes, skipping the newline. Finally, the last command concatenates the three temporary files and writes the result back to your_file.
From this example it is obvious that we can do any text manipulation if we have a way to find the appropriate byte offsets. This will be explained in the Implementation notes below.
One point to note is that, although we cannot use some common commands line "cat", we can quite easily avoid using it (see last command in the example).
I could have used "echo" to insert the replacement string in
a temporary file, but it is easier to write a shell function which
emulates it using (what else?) dd: some implementations
use -n to remove the extra newline, other use \c,
other might even not implement "echo" as a shell builtin! We
don't need to worry about that - we have our own!
Usage of
dd-exdd-ex maintains a notion of current file (initially none)
and of current line within the file. All text manipulation happens on
the current line. The available commands are described below, divided
by category.
To leave the editor, type "quit"
open file
new file
open, but creates the file if needed.
close
save
save file
name file
saves to behave as
"save file"
discard
next
prev
next,
it has some rudimentary checks so it doesn't try to move before the
beginning of file.
goto n
next or prev as necessary,
so the same remarks about end of file apply.
replace string1 string2
*, as the editor has
no way to know the length of the pattern matched and will replace
the wrong text. You are welcome to fix this and send me the patch.
nreplace n string1 string2
replace, except that it looks for the n-th
occurrence of "string1"
delete
next
insert text
print
autoprint
open, new,
prev, next, goto,
insert, delete, replace,
and insert to print the current line after execution.
It is equivalent to typing print after each such command
noprint
Note that not all the functions are actually used - this is meant as a
toolkit which you can use to create your own editor (such as, for example,
an implementation of emacs with complete elisp support),
so I have provided extra functions whenever it was easy to do so.
dd!, needed
to compute line numbers, offsets, and so on
echo, which we redefine
for the reasons stated before