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