[sed] macOSでもLinuxでもsedを使ってtab文字を置換する


要約

ASCIIコードを用いることで、macOSでもLinuxでも同じ書き方でtab文字を置換できるようになります。

TAB="$(printf '\\\011')"
printf "hoge\tfuga\n" | sed "s/${TAB}/,/g"

sedのOS依存 (BSD sed vs GNU sed)

sedの使用例として、タブ区切りをコンマ区切りにする下記のスクリプトをよく用いていました。

# Linux
$ printf "foo\tbar\n"
foo    bar
$ printf "foo\tbar\n" | sed "s/\t/,/g"
foo,bar

しかしの方法ではmacOSではうまく置換できません。

# macOS
$ printf "foo\tbar\n"
foo    bar
$ printf "foo\tbar\n" | sed "s/\t/,/g"
foo    bar # <-変わっていない!

どうやらこの違いはmacOSはBSD sedで、LinuxはGNU sedを使用していることに起因するようです。

BSD sedでタブ文字置換をどうするかついて、過去のQiita記事にございました

(同じタイトルですが、違う記事です)

しかし上記事の方法は使用状況が限られるため、もう少し汎用性を持ちたいと思っていたところ、次の記事がございました。

上記事では以下のようにASCIIコードを使ってLF(改行)を表現していました。

LF=$(printf '\\\012_')
LF=${LF%_}

echo "hogehoge\nfoo\nbar" | sed 's/\\n/'"$LF"'/g'

この方法はそのままタブ文字に応用できるのでは、と思って検証したところ、無事に動作しました。

# ASCIIコードで水平タブ(HT)は011です
TAB="$(printf '\\\011')" 
printf "hoge\tfuga\n" | sed "s/${TAB}/,/g"

これでmacOSでもLinuxでも、同じ書き方でtab文字を置換できるようになりました。

検証環境

# macOS
- OS: Catalina 10.15.6 19G2021 x86_64
- Kernel: 19.6.0
- Shell: zsh 5.7.1

# Linux
- OS: Linux Mint 20 x86_64
- kernel: 5.4.0-47-generic
- shell: bash 5.0.17