BSD環境での制御コードの置換について
昨日のシェル芸ヴェンキョウカイ(問2)で話題になった、BSD系環境で制御コードを置換するはなしです。
sedではやれないけどtrなら……という話です。
BSDでも、trを使えば8進数で置換できるみたい。
comm <(sort a) <(sort b) | sort -r | tr '\011' ','
#シェル芸
— くんす (・8・) と (@kunst1080) 2015, 8月 29
内容
概要
問2の模範解答は
comm <(sort a) <(sort b) | sed 's/^/\t/' | sed 's/\t\t\t/c /' | sed 's/\t\t/b /' | sed 's/\t/a /' | sort
となっています。
これは「先頭にtabを突っ込んで、タブの連続を置換していく」という解き方で、GNU sedの利用を前提としています。
今回は解説のため、まずはBSDのsedとtrを使った別解を書いてみます。
tabの代わりにカンマ(,)を使用するという発想です。
% comm <(sort a) <(sort b) | tr '\011' ',' | sed 's/^/,/' | sed 's/,,,/c /' | sed 's/,,/b /' | sed 's/,/a /' | sort a 川崎 a 鹿島田 b 南多摩 b 登戸 c 分倍河原 c 谷保
trの部分の解説
trの前で止めるとこうなっていて
% comm <(sort a) <(sort b) 分倍河原 南多摩 川崎 登戸 谷保 鹿島田
※commコマンドの話は後でしますが、データがタブ区切りになっています
trの後で止めるとこうなっています。
% comm <(sort a) <(sort b) | tr '\011' ',' ,,分倍河原 ,南多摩 川崎 ,登戸 ,,谷保 鹿島田
さて、manによると
\octal
バックスラッシュに続き、1〜3 桁の 8 進数が続いたものは、その値 を符号化した文字を表現します。この 8 進数の並びに続いて数字を 文字として指定したい場合には、8 進数の並びが 3 桁となるよう に、8 進数の上位桁 (左) に 0 を埋めてください
とのことです。
つまり
tr '\011' ','
は、ASCIIコードでtab(16進数で09、8進数で11)をカンマ(,)に置換する、ということになります。
どんでん返しその1
さっきの、sedのmanの続きです……
\character
バックスラッシュに続く、特定の特殊な文字は、特殊な値に対応しています。\a <ベル文字>
\b <バックスペース>
\f <フォームフィード>
\n <改行>
\r <復帰>
\t <水平タブ>
\v <垂直タブ>
trは普通にバックスラッシュ文字が使えました……そういえばそうだった……
つまり
% comm <(sort a) <(sort b) | tr '\t' ',' | sed 's/^/,/' | sed 's/,,,/c /' | sed 's/,,/b /' | sed 's/,/a /' | sort
でいいってことですよ奥さん!!