初めまして、シナプスの技術部ネットワーク課の岩元と申します。 未経験で入社し、現在シナプスのインフラエンジニアとしてお仕事をさせて頂いております。
私自身サーバを扱った経験がなく、しばらく Linux について勉強しているなかで、 sed コマンドというものを知り、大変便利だと感じました。エンジニアの界隈では、多数の人たちに理解あるコマンドかと思いますが、 自分が初心者ということもあり、備忘録も兼ねて今回sedについて学んだことをまとめてみました。
sed コマンドのオンラインマニュアル www.gnu.org
sed の基本情報
sedコマンドはフィルタを作成したり、エディタを開かずにファイルを直接編集できる、とても有用なコマンドです。 標準入力から受け取ったデータを編集し、標準出力に書き出します。
書式・オプション・コマンドについて以下にまとめます。
書式
- sed [オプション] コマンド [ファイル]
- sed [オプション] -e コマンド1 [ -e コマンド2 ... ] [ファイル]
- sed [オプション] -f スクリプト [ファイル]
主なオプション
オプション | 意味 |
---|---|
-e | 処理内容を指定する。コマンドを続けて指定する場合に必須のオプション |
-i | 処理した内容でファイルを上書きする |
-n | 編集した各行の自動出力をさせない(p コマンドとの併用時に設定可能) |
-f | コマンドが書かれたスクリプトファイルを指定する |
-E , -r | 拡張正規表現を使う |
編集コマンド
置換・表示・削除などの操作を指定するためのコマンドです。
sed の基本操作
sed の置換機能について
sed で最もよく使われる操作が置換機能です。 s/old/new/ という置換用の編集コマンドは "/" で囲んだ2つの文字列のうち、左側の文字列を右側の文字列に置き換えることができます。 各行につき1番目に見つけた最初の文字列のみ置換ができます。
# cat sample01.txt old old old old old old # sed -e 's/old/new/' sample01.txt new old old new old old
gコマンドを付与し、s/old/new/g とすることで、1行の中で見つけた文字列を全て置換させることができます。
# sed -e 's/old/new/g' sample01.txt new new new new new new
sed の出力内容の制御
"-n" というオプションを付けると、編集した結果を出力させないようにできます。
# cat sample02.txt old 000 111 aaa bbb # sed -n -e 's/old/new/g' sample02.txt # <- 何も表示されない
"-n"と一緒に print(出力しなさい) という意味のコマンド"p"を使うことで、編集した対象の行のみを 表示させることができます。(対象外の余分な行は出力を非表示にできます)
# sed -e 's/old/new/g' sample02.txt new <- 編集対象の行 000 111 <- 余分な行 aaa bbb <- 余分な行 # sed -n -e 's/old/new/gp' sample02.txt new <- 編集対象の行のみ出力される
デリミタについて
置換コマンドで、区切りに使う “/”(スラッシュ) という文字を「デリミタ」と呼びます。 置換したい文字列内に"/"がある場合は、デリミタと解釈されないように "\ /" としてエスケープさせると良いのですが、 "/"が多用に含まれてしまうと視認性が下がるため、 デリミタの文字を、他の文字に変えて表記する場合もあります。(下記の例では"@"を使用)
# cat sample03.txt who command: file /var/log/wtmp # sed -e 's@/var/log/wtmp@/var/run/utmp@' sample03.txt who command: file /var/run/utmp
基本的なコマンド例
ここでは、ファイルの編集でよく使うコマンドの例を紹介していきます。
置換機能を利用した編集例
「old」という文字列の削除
sed -e 's/old//g' file
行頭の「oldtext」という文字列を削除
sed -e 's/^oldtext//' file
行末の「oldtext」という文字列を削除
sed -e 's/oldtext$//' file
行頭に文字列「add」を追加
sed -e 's/^/add/' file
行末に文字列「add」を追加
sed -e 's/$/add/' file
正規表現を使った編集例
行頭から3文字をすべて削除
sed -e 's/^...//' file
行の全てを「abcd」という文字列に置換
sed -e 's/.*/abcd/' file
「s」という文字まで削除
sed -e 's/.*s//' file
括弧の中の文字列を削除
sed -e 's/(.*)/()/' file
1~9までの数字を0に置換
sed -e 's/[1-9]/0/g' file
英字(小文字)を削除
sed -e 's/[a-z]//g' file
行単位の編集例
1~4行目を対象に置換
sed -e '1,4s/oldtext/newtext/g' file
5行目から最終行までを対象に置換
sed -e '5,$s/oldtext/newtext/g' file
キーワードによる行の指定
例) "begin"を含む行から、"end"を含む行までを削除
sed -e '/begin/,/end/d' file
dコマンドの例
1行目を削除
sed -e '1d' file
1~4行目まで削除
sed -e '1,4d' file
空白の行を削除
sed -e '/^$/d' file
pコマンドの例
2行目だけを表示
sed -n '2p' file
最初の行から5行目までを表示
sed -n '1,5p' file
最終行を表示
sed -n '$p' file
応用的な sed の使い方
少々応用的ですが、sed コマンドを業務で活用する際に、知っておくことで大変便利だと感じた使い方について紹介していきます。
ホワイトスペースの処理
ホワイトスペースとは、タブや、スペースのような空白文字のことです。 タブが入っているのか、スペースが入っているのか分からない状態でも、 以下のコマンドを実行することで、まとめてホワイトスペースを削除できます。
sed -e 's/[ \t]\+//g' file sed -e 's/\s\+//g' file
・実行例
# cat whspace.txt He ll o, I m sy nap s e e ngi n e er ! # sed -e 's/[ \t]\+//g' whspace.txt Hello,Im synapse engineer!
正規表現 [ \t]の、(" ")は spaceキー、(\t)は tabキーを意味しております。
タブとスペースの混在を意味する上記の"[ \t]"や、ホワイトスペースそのものを意味する"\s"を正規表現で使うことで、まとめて処理させることができます。
ファイルの上書き
"-i " オプションで、編集した結果を、対象のファイルに上書きさせることができます。
sed -i '/oldtext/d' file
「-i.org」のように、オプションの後ろに末尾名を付けることで、その末尾名が付いたバックアップファイルを作成しておくことも可能です。
sed -i.org '/oldtext/d' file
・実行例
# cat test.txt oldtext newtext # ls -l test.* -rw-r--r-- 1 root root 16 Sep 27 19:24 test.txt ○バックアップ作成と編集を同時に実行 # sed -i.org '/oldtext/d' test.txt ○ファイル確認 # ls -l test.* -rw-r--r-- 1 root root 8 Sep 27 19:26 test.txt -rw-r--r-- 1 root root 16 Sep 27 19:24 test.txt.org ↑末尾が「.org」のバックアップファイルが保存されている # cat test.txt newtext # cat test.txt.org oldtext newtext ↑編集前のファイルの中身が残っている
改行コードの変換
Windows や、MacOS、Linux(Unix)では、以下のように使用する改行コードが異なります。
OS | 改行コード | 正規表現 |
---|---|---|
Unix | LF(ラインフィールド) | \n |
Mac(OSX) | LF(ラインフィールド) | \n |
Mac (OS9) | CR(キャリッジリターン) | \r |
Windows | CR+LF | \r\n |
「od -c」コマンドで、ファイルに使われている改行コードを確認することができます。 例えば、以下のファイルは改行コードが"\r"と"\n"で表示されているので、CR+LFであることが分かります。
# od -c winline.txt
0000000 a b c d e \r \n f g h i j \r \n k l
0000020 m n o \r \n p q i s t \r \n u v w x
0000040 y z \r \n
0000044
Linux に対応した改行コードに変換させる時は、CR+LF を LFに変換させればよいので、sed コマンドで"\r"を削除してあげることで解決できます。
sed -i 's/\r//g' winline.txt
・実行例
# sed -i 's/\r//g' winline.txt
# od -c winline.txt
0000000 a b c d e \n f g h i j \n k l m n
0000020 o \n p q i s t \n u v w x y z \n
0000037
その他、各改行コードの変換は以下の通りです。
- CR+LF を CRに変換
sed -i 's/\n//g' file
- LF をCR+LFに変換
sed -i 's/$/\r/g' file
異なる階層で複数のファイルを一括編集
以下のようなディレクトリの階層と、ファイルが存在しているとき、
# tree --charset=C . |-- dir1 | |-- 1.txt | `-- dir11 | |-- 11.exe | |-- 11.img | `-- 11.txt |-- dir2 | |-- 2.img | `-- 2.txt `-- dir3 |-- 3.img `-- 3.txt 4 directories, 8 files # cat dir1/1.txt 12345 # cat dir1/dir11/11.txt 12345 # cat dir2/2.txt 12345 # cat dir3/3.txt 12345
末尾が「.txt」のファイルを一括して編集したい場合、sed に find コマンドと、xargs コマンドを組み合わせることで、まとめて編集できます。
find . -type f -name "*.txt" | xargs sed -i '<編集コマンド>'
・実行例
find . -type f -name "*.txt" | xargs sed -i 's/[1-5]/N/g' # cat dir1/1.txt NNNNN # cat dir1/dir11/11.txt NNNNN # cat dir2/2.txt NNNNN # cat dir3/3.txt NNNNN
xargs は、コマンドの実行結果を、次のコマンドの引数に受け渡すことができます。 「find . -type f -name "*.txt"」により、検索された「.txt」のファイルのリストを、パイプ先の sed コマンドの引数に引き渡すことで、対象のファイルを編集することができます。
参考書籍
今回、Linux のシェルについて学習するにあたり、以下の書籍を参考に学習しました。
こちらの書籍ですが、実務で活用するコマンドや、シェル関数・シェルスクリプトの書き方についてとても詳しく解説しており、 私のような初心者には勿論のこと、仕事に慣れた中級者の方々ににも大変オススメの書籍です。まとめ
- コマンドの一つ一つの意味を深く学習したことで、様々な使い方について学ぶことができました。
- sedコマンドは実務で活用できる、大変便利なコマンドですので、Linux 初心者の方たちに是非おすすめです。
- 私自身まだまだ慣れていない部分も多いですが、サーバの運用をしていく上で、今回学んだことを日々の業務でも活かせるようにしたいと思います。