はじめに

編集

sedはストリームエディタ(Stream Editor)の略で、テキストの変換処理を行うための強力なツールです。パイプラインでの処理や、ファイルの一括編集に適しています。

sedの特徴

編集
  • 行指向の処理
  • 正規表現によるパターンマッチング
  • スクリプトによる自動編集
  • 最小限のメモリ使用

基本構文

編集
sed [オプション] 'コマンド' [入力ファイル]
sed [オプション] -f スクリプトファイル [入力ファイル]

基本コマンド

編集

置換(s/)

編集
# 基本的な置換
sed 's/old/new/'        # 各行の最初のマッチを置換
sed 's/old/new/g'       # 各行のすべてのマッチを置換
sed 's/old/new/2'       # 各行の2番目のマッチを置換
sed 's/old/new/ig'      # 大文字小文字を区別せずに置換

削除(d)

編集
sed '3d'                # 3行目を削除
sed '1,5d'             # 1-5行目を削除
sed '/pattern/d'       # パターンにマッチする行を削除
sed '/start/,/end/d'   # 開始パターンから終了パターンまでを削除

追加と挿入(a\, i\)

編集
sed '2a\新しい行'       # 2行目の後に行を追加
sed '2i\新しい行'       # 2行目の前に行を追加
sed '/pattern/a\新しい行' # パターンマッチした行の後に追加

変更(c\)

編集
sed '2c\置換後の行'     # 2行目を完全に置換
sed '/pattern/c\新しい行' # パターンマッチした行を置換

高度な機能

編集

アドレス指定

編集
# 行番号による指定
sed '1,10s/old/new/g'   # 1-10行目で置換
sed '2,+5s/old/new/g'   # 2行目から5行分で置換

# パターンによる指定
sed '/start/,/end/s/old/new/g'  # パターン間で置換
sed '/regex/!s/old/new/g'       # パターンにマッチしない行で置換

保持スペース操作

編集
# h, H (パターンスペース→保持スペース)
sed 'h;n;H;x;s/\n/ /'   # 2行を1行に結合

# g, G (保持スペース→パターンスペース)
sed '/pattern/{h;d};$G'  # パターンマッチした最後の行を最終行に移動

# x (パターンスペースと保持スペースの交換)
sed 'x;1d;$G'           # 行の順序を逆転

複数コマンドの実行

編集
# セミコロンで区切る
sed 's/old/new/;s/foo/bar/'

# -eオプションを使用
sed -e 's/old/new/' -e 's/foo/bar/'

# スクリプトファイルを使用
cat script.sed
s/old/new/
s/foo/bar/

実践的な使用例

編集

ファイル加工

編集
# コメント行の削除
sed '/^#/d' config.txt

# 空行の削除
sed '/^$/d' file.txt

# 行頭と行末の空白を削除
sed 's/^[ \t]*//;s/[ \t]*$//' file.txt

テキスト整形

編集
# 各行をダブルクォートで囲む
sed 's/.*/"&"/' file.txt

# カンマ区切りをタブ区切りに変換
sed 's/,/\t/g' data.csv

# XMLタグの除去
sed 's/<[^>]*>//g' file.xml

プログラミング的な処理

編集
# 行番号の付与
sed = file.txt | sed 'N;s/\n/\t/'

# 特定パターン間の行を抽出
sed -n '/start/,/end/p' file.txt

# 条件分岐
sed '/pattern/{s/old/new/;b};s/other/replace/' file.txt

高度な技術

編集

ラベルとブランチ

編集
# ラベルの定義と分岐
sed ':start
     s/old/new/
     t start' file.txt

# 条件付きブランチ
sed '/pattern/{
     s/old/new/
     b next
     }
     s/other/replace/
     :next' file.txt

サブシェルコマンドの実行

編集
# 現在の日時を挿入
sed "s/DATE/$(date)/" template.txt

# 外部コマンドの結果を使用
sed "s/VERSION/$(git describe)/" version.txt

付録A: sedイディオム集

編集

A.1 テキスト処理イディオム

編集
# 行の重複を除去(uniq相当)
sed '$!N; /^\(.*\)\n\1$/!P; D'

# 行の順序を逆転
sed '1!G;h;$!d'

# 各行の前に行番号を付加
sed = file | sed 'N;s/\n/\t/'

# 特定の行を2回繰り返す
sed 'p;n' file        # 奇数行を繰り返す
sed 'n;p' file        # 偶数行を繰り返す

A.2 ファイル加工イディオム

編集
# 末尾に改行がないファイルに改行を追加
sed '$a\'

# ファイルの先頭にヘッダーを追加
sed '1i\# Configuration File' config.txt

# ファイルの末尾にフッターを追加
sed '$a\# End of file' config.txt

# Windows形式の改行(CRLF)をUnix形式(LF)に変換
sed 's/\r$//'

A.3 プログラミング的イディオム

編集
# 複数パターンの一括置換
sed -e 's/pattern1/replace1/g' \
    -e 's/pattern2/replace2/g' \
    -e 's/pattern3/replace3/g'

# 特定範囲のみで置換を実行
sed '/start/,/end/{
    s/old/new/g
}'

# 条件付き処理
sed '/pattern/{
    /exclude/!{
        s/old/new/g
    }
}'

付録B: sedベストプラクティス

編集

B.1 スクリプト構造

編集
#!/bin/sed -f

# メタ情報
# Author: name
# Date: YYYY-MM-DD
# Description: スクリプトの目的

# 初期処理
1{
    # ヘッダー処理
    i\# 処理開始
}

# メイン処理
/pattern/{
    # パターンに対する処理
    s/old/new/g
    b next_label
}

# 終了処理
${
    # フッター処理
    a\# 処理終了
}

B.2 保守性のための指針

編集
  1. コメントを適切に使用する
       # 複雑な正規表現には説明を付ける
       s/[0-9]{4}-[0-9]{2}-[0-9]{2}/& 00:00:00/  # 日付に時刻を追加
    
  2. 複雑な処理は分割する
       # 複数の処理を論理的に分割
       /pattern/{
           # 前処理
           s/prefix_//
           
           # メイン処理
           s/old/new/
           
           # 後処理
           s/$/_suffix/
       }
    
  3. エラー処理を含める
       # 入力検証
       /^[^0-9]*$/{ 
           i\Error: Invalid input format
           d
       }
    

B.3 パフォーマンス最適化

編集
  1. 効率的なパターンマッチング
       # 悪い例
       s/.*pattern.*/matched/
       
       # 良い例
       /pattern/s/.*/matched/
    
  2. 不要な処理を避ける
       # 条件が合わない行はスキップ
       /pattern/!b
       
       # 必要な処理のみ実行
       s/old/new/
    
  3. バッファの効率的な使用
       # 必要な場合のみ保持スペースを使用
       /pattern/{
           h    # 保持スペースに保存
           d    # 次の行へ
       }
       ${ 
           g    # 保持スペースから復元
       }
    

B.4 デバッグとトレース

編集
# デバッグ出力
/pattern/{
    l    # パターンスペースの内容を表示
    /debug/p    # デバッグ行を表示
}

# 処理の追跡
/#DEBUG/{
    i\=== Processing line ===
    l
    i\==================
}

これらのベストプラクティスとイディオムを適切に組み合わせることで、より保守性が高く、効率的なsedスクリプトを作成することができます。