サーバエンジニアの知恵袋 - sed の使い方

sed の基本

コマンドライン構文


$ sed [ -n ] [ -e ] 'command' file(s)
$ sed [ -n ] [ -f ] scriptfile file(s)

sed コマンドの構文


[ address [ ,address ] ] [ ! ] command [ arguments ]

標準的な使い方は、次のようになる。

$ sed -e 's/OldText/NewText/' samplefile

この例は、samplefile の中の、"OldText" という文字列を "NewText" という文字列に変換し、標準出力に出力する。

"-e"オプションは、その後の文字列が編集用のコマンドであると示すものである。通常は編集用コマンドを複数指定する場合に使う。編集用コマンドが1つだけの場合は"-e"は省略することができる。

ファイルが指定されていない場合は、標準入力を処理する。

sed はデフォルトでは、変換対象では無い行も含めすべての行を標準出力に出力するが、文字列を置き換えた行だけを出力するには、"-n"オプションを使用する。
"-n"オプションを使うときは、必ず"p"を合わせて使う必要がある。

$ sed -n -e 's/OldText/NewText/p' samplefile

sed コマンドのデリミタの変更


通常は"/"をデリミタとして使用するが、別の記号をデリミタにすることもできる。文字列の中に"/"が含まれている場合などにデリミタを変更すると良い。デリミタを変更するためには、特別な宣言をする必要はない。
以下の例では、デリミタを "%" にしている。

$ sed -e 's%OldText%NewText%'

ドット(.)とアスタリスク(*)


ドット(.) : 任意の1文字を表す
アスタリスク(*) : 直前の文字が任意の個数(0個も含む)連続することを表す

例)
"..." : 任意の3文字
"a*" : a, aa, aaa など、a が任意の個数続く文字列
".*" : 任意の文字列。どんな文字列もマッチする。(Nullも含む)

文字列の変換


OldText という文字列を NewText という文字列に変換する。
g がなければ、その行に出てくる最初の文字列だけを対象にする。

$ sed -e 's/OldText/NewText/'

g を付けると行全部を対象にする。

$ sed -e 's/OldText/NewText/g'
行を指定した変換(以下の例では5行目から20行目までを処理する。)

$ sed -e '5,20s/OldText/NewText/g'
5行目から最終行までを処理する場合

$ sed -e '5,$s/OldText/NewText/g'
複数のスペースを1個のスペースに変換

$ sed -e 's/<space><space>*/<space>/g'

文字列の削除

Textという文字列を削除する。
gがなければ、その行に出てくる最初の文字列だけを対象にする。gがあれば全部を対象にする。

$ sed -e 's/Text//g'
Patternという文字列から行末までを削除

$ sed -e 's/Pattern.*//'
Pattern1で始まり Pattern2 で終わる文字列を消去

$ sed -e 's/Pattern1.*Pattern2//'
行頭の文字列の削除
行の最初にTextという文字列がある場合に、その文字列を削除する。ここではgを付ける意味は無い。

$ sed -e 's/^Text//'
行末の文字列を削除
行の最後にTextという文字列がある場合に、その文字列を削除する。
$はシェルに解釈させないように\でエスケープする必要がある。

$ sed -e "s/Text\$//"

「"」の代わりに「'」を使うとエスケープする必要が無い。

$ sed -e 's/Text$//'
コメントの削除

$ sed -e 's/#.*//' file

文字列の追加


文字列の追加は、行頭か行末だけ。(任意の場所に追加することはできない。)
行頭に文字列を追加
対象ファイルの全部の行頭にTextという文字列を追加する。

$ sed -e 's/^/Text/'
行末に文字列を追加
対象ファイルの全部の行末にTextという文字列を追加する。

$ sed -e 's/$/Text/'

文字列の取り出し


例1) id コマンドの出力結果から ID を取り出す

id の出力

$ id 
uid=1001(user) gid=1000(usergrp)

$ id | sed -e 's/uid=//' -e 's/(.*//'
1001

文字列 "uid="と "("以降の文字列を削除している。

例2) id コマンドのユーザ名を取り出す

$ id | sed -e 's/uid=.*(\(.*\)) gid=.*/\1/'
user

最初の".*" はユーザID, 2番目の".*"はユーザ名を表し、"gid=.*"が残りの部分を表している。
取り出したいのは2番目の".*"の部分なので、丸括弧を使って取り出したい部分を括り、後ろの"//"部分を"/\1/と指定することで取り出している。
つまり、 \(〜\) で囲んだ部分は、\1, \2, \3 ・・・で後方参照することができる。

例3) 文字列の最初から5文字分を切り取る

$ sed -e 's/^\(.....\).*/\1/' file

□awk を使う場合

例1) 文字列の最初から5文字分を切り取る

$ awk '{printf "%-.5s\n", $0}' <file

□cut を使う場合

$ echo "STRING" | cut -c1-5

行の削除

Text という文字列を含んだ行を削除する。

$ sed -e '/Text/d'

grep を使うと以下のようにできる。

$ grep -v "Text"
空白行の削除

$ sed -e '/^$/d'
スペースやタブだけの行も削除する場合は以下のようにする。

$ sed -e '/^[<space><tab>]*$/d'
ファイルの1行目を削除

$ sed -e '1d' file
ファイルの1行目から4行目までを削除

$ sed -e '1,4d' file
ファイルの最終行を削除

$ sed -e '$d' file

指定した行のみの表示

1行目だけを表示

$ sed -n '1p' file
3行目から10行目だけを表示

$ sed -n '3,10p' file
最終行のみを表示

$ sed -n '$p' file

大文字と小文字の入れ替え


(sed では無いがおまけ。)
fileの中身を全て小文字にしfile1に出力する。

$ cat file | tr '[A-Z]' '[a-z]' > file1

□参考

ITpro
http://itpro.nikkeibp.co.jp/article/COLUMN/2006022...