テキストレコードのフィールドにセパレータを含むデータを埋め込みたい

問題編

テキストデータを、改行区切りのテキストレコードに埋め込んで出力したい。例えばusp Tukubaiでいうところのネーム形式フィールド形式のフィールドの値として出力したい。

問題は、元データに改行が含まれている可能性があることだ。また、フィールド形式の場合、元データに空白文字が含まれている可能性も見逃せない。フィールドに埋め込む前に、改行や空白文字をエスケープする必要がある。

C言語系統の言語やUnix環境のツールのように「\n」のような記号を使用するのは、可読性の面では望ましい。しかし、この手のエスケープ記号を使って手作業でデータを作ることや、エスケープ記号を処理するコードを書くのは難しくないのだが、エスケープを行うコードを書くのは少々面倒だ*1

また、フィールドのセパレータに関しては、空白文字以外にも「:」とか「|」とか「,」とかありえる訳で、記号が変わるたびにエスケープの処理を拵えるのも面倒だ。

何か別のアイデアはないだろうか?

解答編(暫定)

少々大胆な仮定をしてみることにした。

  • セパレータとして使用される可能性がある文字は、空白文字か記号文字だけである。

この仮定の下では、フィールドの値として無条件に使用できるのは数字か普通の文字(ASCII文字でいうところのアルファベット文字)のみである。

いちいちエスケープが必要な部分を探して変換するのは面倒なので、16進ダンプしてしまうことにする。

元のデータを16進ダンプするのは難しくない。

# od(1) と tr(1) は大抵の環境に用意されているはず
echo -n hello world | od -A n -t x1 -v | tr -d ' '
# => 68656c6c6f20776f726c64

# hexdump(1) は時々標準では入ってないことがある
echo -n hello world | hexdump -v -e '2/1 "%02X"'
# => 68656C6C6F20776F726C64

16進ダンプから元に戻す処理については、手ごろなテキストフィルタが見つからなかったので、自作してみた。
https://github.com/eel3/hexdecode
上記のコマンドを使用して、データをテキストレコードのフィールドに埋め込む前に16進ダンプしておき、レコードからフィールドを取り出す際にデコードして元に戻すようにする。

16進ダンプ案の前にbase64(1)を使うことも考えたが、「+」や「/」が出現することは容認できたが、LinuxMac OS Xとでオプション引数が異なることは容認できなかった。

*1:例えば改行を「\n」にエスケープするなら、元々「\n」と書かれていた部分をケアする必要がある。