Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

ワンライナーでお手軽実行可能なsed入門

More than 5 years have passed since last update.

ワンライナー!ワンライナー!

みんな大好きワンライナー。
たくさん使いこなせるとイケメンですね^^

複数行のほうがカッコイイぜという変態の方は大変申し訳ありませんが対象外となります。

普通のコマンドはいくつかの引数(オプション等)を覚えればおしまいですが、sedはそう簡単にはいきません。

sedは、ストリームエディタ(Stream EDitor)の略でテキスト処理を行うプログラムです。文字列を置換したりする際によく使いますね。

sedの書式は、vimなんかでもよく使ったりするので積極的に覚えましょう。

sed書式

# スクリプトを直接指定
$ sed -e 'スクリプト'

# スクリプトが記述されているファイルを指定
$ sed -f 'スクリプトファイル名'

# 表示を抑制(明示的にスクリプト中でpをすれば表示も可能)
$ sed -n 'スクリプト'

# 拡張正規表現を使ったスクリプトを記述
$ sed -r '正規表現を使ったスクリプト'

スクリプト部分はざっくり言うと以下の様な構成です
「スクリプト=範囲指定+コマンド」

sed使用例

以下BSD sed, GNU sedで動作確認しています。

基本的な文字列処理

マッチした文字列を置換する

$ echo 'before text' | sed 's/before/after/'

after text

マッチした文字列をすべて置換する

$ echo 'before before before text' | sed 's/before/after/g'

after after after text

複数の文字列を一度に置換する

# before1→afterA、before2→afterBに置換
$ echo 'before1before2' | sed 's/before1/afterA/;s/before2/afterB/'

afterAafterB

置換時にマッチしたキーワードを再利用する

# githubというマッチしたキーワードを&で再利用
$ echo 'github' | sed 's/github/I like &./'

I like github.

1文字づつ置換する

# eとoをEとOに置換する
$ echo -e "book\nball\norange\nmelon\npen\nmouse" | sed 'y/eo/EO/'

bOOk
ball
OrangE
mElOn
pEn
mOusE

範囲を限定したテキスト処理

最初にマッチしたものだけ置換する

# 1行目からccccのある行までを探索し、ccccをeeeeに置換
# sの前には1,3とか数値だけを指定してもいい
$ echo -e "aaaa\nbbbb\ncccc\ndddd\ncccc" | sed '1,/cccc/s/cccc/eeee/'

aaaa
bbbb
eeee # 最初にマッチしたので置換されている
dddd
cccc # 最初のマッチじゃないため置換されない

指定範囲の行を削除する

# aaaaからccccまでの範囲を削除
$ echo -e "aaaa\nbbbb\ncccc\ndddd" | sed '/aaaa/,/cccc/d'

dddd


# 1行目から2行目までを削除する
$ echo -e "aaaa\nbbbb\ncccc\ndddd" | sed '1,2d'

cccc
dddd


# 空行または#で始まるコメント行削除
$ echo -e '1:one\n2:two\n\n# 3:three\n4:four' | sed '/^$/,/^#/d'

1:one
2:two
4:four

指定範囲の行を表示する

# aaaaからccccまでの範囲を表示
$ echo -e "aaaa\nbbbb\ncccc\ndddd" | sed -n '/aaaa/,/cccc/p'

aaaa
bbbb
cccc

# 3行目から最後の行までの範囲を表示
$ echo -e "aaaa\nbbbb\ncccc\ndddd" | sed -n '3,$p'

cccc
dddd

指定行以外を表示する

# 2行目以外を表示
$ echo -e "aaaa\nbbbb\ncccc\ndddd" | sed -n '2!p'

bbbb
cccc

ファイル内の指定行のみ出力

# file1.txtの10行目を取得
$ sed -n 10p file1.txt

指定行にデータを挿入

# 1行目に######を挿入(iはマッチ行の手前)
# echo -e "aaaa\nbbbb\ncccc\ndddd" | sed '1i\######'

######
aaaa
bbbb
cccc
dddd

# 最終行に######を挿入(aはマッチ行の後)
# echo -e "aaaa\nbbbb\ncccc\ndddd" | sed '$a\######'

aaaa
bbbb
cccc
dddd
######

正規表現を使った文字列置換

実際にコーディングしたり設定を書き換えたりするには正規表現が必須ですね。

マッチした文字列の一部を再利用する

()でくくれば、置換後文字列で\1,\2,\3・・・のように部分的に再利用できます。
ただし()はそれぞれ\(,\)とエスケープしてやる必要があります。

# phpのテンプレコードをruby(erb)コードに変換する
$ echo -e "<?php echo 'hogehoge'; ?>" | sed 's/<?php echo \(.*\); ?>/<%= \1 %>/'

<%= 'hogehoge' %>

最短マッチさせる

# <a href="http://www.yahoo.co.jp/" class="others">Yahoo!</a>からURL抽出する

# (NG例)不用意に.*を使うと意図せぬマッチングになってしまう
$ echo -e '<a href="http://www.yahoo.co.jp/" class="others">Yahoo!</a>' | sed 's/<a href="\(.*\)".*$/\1/'

http://www.yahoo.co.jp/" class="others 

# (OK例)最短マッチ ([^"]*で"以外のすべての文字の繰り返しとして指定)
$ echo -e '<a href="http://www.yahoo.co.jp/" class="others">Yahoo!</a>' | sed 's/<a href="\([^"]*\)".*$/\1/'

http://www.yahoo.co.jp/

応用例

ログ監視

指定日・指定時間のaccess_logを見る

※apacheのログ書式に応じてフォーマットを見なおしてください

# 02/May/2014を含む行を表示
$ cat /var/log/apache2/access_log | sed -n '/02\/May\/2014/p'

# 02/May/2014の22時台の行を表示
$ cat /var/log/apache2/access_log | sed -n '/02\/May\/2014:22/,/02\/May\/2014:23/p

root以外のsyslogを見る

grep -vでもいいんですけどね・・・。

# rootを含まない行を表示
$ cat /var/log/syslog | sed -n '/root/!p'

Web解析

WebページからURL一覧抽出

わざわざプログラム組まなくてもできます。

# hrefの中身だけを抽出してリストアップ
# 1行に2つ以上aタグがある場合は対応できていません。
$ curl http://b.hatena.ne.jp/hotentry/it | sed -n 's/^.*href="\([^"]*\)".*$/\1/p'

Webページから記事タイトルを抽出してリストアップ

# 上とは別の例としてegrepでaタグに絞込み
# その後sedでタグを除去し、行頭のスペースを除去
$ curl http://b.hatena.ne.jp/hotentry/it | egrep "<a.*entry-link" | sed 's/<[^>]*>//g;s/ //g'
muran001
2014年6月から大手SIerに見切りをつけてWeb系のエンジニアとして活動してます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away