sedコマンドで文字列を改行に置換する、しかもスマートに置換する。

  • 75
    いいね
  • 8
    コメント
この記事は最終更新日から1年以上が経過しています。

概要

  1. sedコマンドで任意の文字列を改行に置換する方法
  2. 知ってはいるけど記述が汚いのでもっと綺麗に書きたい。

そもそも改行ってどーやるの?

例えば、\nって書いてあるところを全部本物の改行に置換したいならこーやります。

nl.sh
echo "hogehoge\nfoo\nbar" | sed 's/\\n/\
/g'

sedの置換コマンド後半部分に、エスケープ用のバックスラッシュと、実際の改行コードを書くわけです。
でもこれって汚い!コマンドの途中で改行されちゃうのはイヤんな感じ。

スマートにいきましょ。

綺麗に書きたければ改行文字をシェル変数に入れておき、実際の改行を書く代わりに使えばいいのです。つまり、シェル変数$LFなどを作ってそこに'\'と'<0x0A>'の2文字を格納し、これを使えばいいのです。

まずは$LFに'\'と'<0x0A>'を入れましょ。

が!素直にはシェル変数には入ってくれません。

一筋縄ではいかない。

printfコマンドを使うとキーボードから打てないコントロール文字も生成できます。(ただし、printfは8進数で指定してくださいね。そうしないとLinux以外でエラーになります) だから'\'と'<0x0A>'の2文字分ということで、

makelf_bad.sh
LF=$(printf '\\\012')

と書くと……、2文字目に指定した改行コードが$LFに入りません。理由は、文字列の最後に改行コードがあると、シェル変数に入る前にカットされてしまうからです。じゃあどうするか???

こうやるといい

だから、シェル変数に入れる時には最後の文字を改行にしなければいいのです。そして、入った後でトリミングするという寸法です。

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

2行目の%は右からのトリミング。右の'_'をトリミングせよという意味です。これでめでたく$LFには'\'と'<0x0A>'が入りました。

これでよーやく、スマートにイケます。

$LFを作るところからまとめて正解を書きます。sedで$LFを使う時は、置換コマンドを前半と末尾に分解し(=シングルクォーテーションで切り)、その間に"$LF"(ダブルクォーテーションも含む)を挿しこめばいいのです。

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

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

理屈を覚えるのはちょっと複雑ですが、覚えてしまえば綺麗なシェルスクリプトが書けます。