sedコマンドによる文字列の置き換え
はじめに
シェルスクリプトで文字列の置換を行う場合、sedコマンドを使うことでこれを実現できます。
忘れた頃に読んで雰囲気を思い出せるようにメモとして幾つかの使用例を記載します。
※本記事ではubuntu:20.04を使用してコマンドを実行しています。試す場合はdocker run -it ubuntu:20.04 bash
で可能です。
sedコマンドの使い方
sedコマンドを使った文字列置換の基本形は以下になります。
sedに続いて区切り文字と置き換えるターゲットの文字列, 置換後の文字列を指定します。
echo hogehogefugafuga | sed s'/hoge/fuga/'
上記の例だと区切り文字はスラッシュ/
, 置き換えるターゲットの文字列はhoge
, 置換後の文字列はfuga
になります。
> echo hogehogefugafuga | sed 's/hoge/fuga/'
fugahogefugafuga
この場合、先頭のhoge
のみfuga
に置き換わります。
全てのhoge
をfuga
に置き換える場合は以下のように文末にgを指定することで実現できます。
> echo hogehogefugafuga | sed 's/hoge/fuga/g'
fugafugafugafuga
また、sedで指定する区切り文字はスラッシュ/
以外にも;
, @
, _
, #
などの文字列を区切り文字として使用可能です。
> echo hogehoge/fugafuga/ | sed 's;hoge/;fuga/;'
hogefuga/fugafuga/
sedコマンドの応用例
1. 検索対象の再利用
&
を使うことで検索対象の再利用が可能になります。
> echo hogehogefugafuga | sed 's/hoge/&&/'
hogehogehogefugafuga
上記のコマンドにおいて&
はhoge
の文字列となり、&&
はhogehoge
となります。
よってhoge
をhogehoge
で置き換えることになるので、上記のような出力結果になります。
2. 後方参照
検索対象を()
で囲うことで順番に番号が振られ、後方参照により、これを呼び出すことが可能です。
> echo hogehogefugafuga | sed 's/\(hoge\)\(fuga\)/\2\1/'
hogefugahogefuga
3. 正規表現の利用
sedは正規表現と組み合わせることもでき、オプションとして-E
を渡すことで拡張正規表現を使用することも可能です。(-rでも可)
拡張正規表現を使うと2の例でのエスケープ文字\
は不要になります。
> echo hogehogefugafuga | sed -E 's/(h...)(f...)/\2\1/'
hogefugahogefuga
.
は任意の文字列となるため、hから始まる4文字の文字列, fから始まる4文字の文字列の連結を表します。
よって3の例では次のような文字列が渡された場合も置き換えを行います。
> echo hogehaaafaaafuga | sed -E 's/(h...)(f...)/\2\1/'
hogefaaahaaafuga
2の例だと置き換える対象が見つからないため、元の文字列が出力されます。
> echo hogehaaafaaafuga | sed 's/\(hoge\)\(fuga\)/\2\1/'
hogehaaafaaafuga
4. 文字列を消す場合
置換後の文字列を指定しない場合は置き換えるターゲットの文字列が削除されます。
> echo hogehogefugafuga | sed 's/hoge//'
hogefugafuga
g
を指定した場合、hoge
は全て削除されます。
> echo hogehogefugafuga | sed 's/hoge//g'
fugafuga
5. 行を操作する
出力された各行に対して処理を行うこともできます。
例えばubuntuのルートディレクトリにあるディレクトリのうちli
という文字列を含むものだけ出力する場合sedを使うと以下のようになります。
> ls
bin dev home lib32 libx32 mnt proc run srv tmp var
boot etc lib lib64 media opt root sbin sys usr
root@82673e1a199c:/# ls | sed -n '/li/p'
lib
lib32
lib64
libx32
liという文字列を含むパターンのみ出力を行います。
また、行番号で出力を指定することも可能です。
> ls | xargs echo
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
> ls | sed -n 1,6p
bin
boot
dev
etc
home
lib
-n
は処理が行われた出力のみ出力するというオプションになります。sedはデフォルトでは処理が行われなかった出力はそのまま出力するため、このオプションをつけないと上記の例は動作しません。
> ls | sed '/li/p'
bin
boot
dev
etc
home
lib
lib
lib32
lib32
lib64
lib64
libx32
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
> ls | sed 1,6p
bin
bin
boot
boot
dev
dev
etc
etc
home
home
lib
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
6. 文字列からコマンドへ整形
sedを使うことでパイプで受け取った文字列をもとにコマンドを実行することも可能です。
> echo hoge.txt | sed 's/^/touch /' | bash
root@82673e1a199c:/# ls
bin dev hoge.txt lib lib64 media opt root sbin sys usr
boot etc home lib32 libx32 mnt proc run srv tmp var
上記の例だとecho hoge.txt | sed 's/^/touch /'
の出力はtouch hoge.txt
となるため、これをbashにパイプで渡すことにより、文字列をコマンドとして実行しています。
^
は文字列の頭を表しており、ここでは置き換えるターゲットには文字列を指定していないため、文字列の先頭をmv
で置き換える操作が行われます。
終わりに
本記事ではsedコマンドについて、使い方を忘れてしまった際に雰囲気を思い出すため、幾つかの使用例を記載しました。
ここで示した使い方以外にもsedコマンドには様々なオプション等が用意されており、正規表現と組み合わせることでより柔軟な対応が可能になります。
自分はコマンドなどすぐ忘れるので、使い方を忘れた際にはここに戻ってきて、シュッと解決できたらと思います。
Discussion