# sed クイックリファレンス

*ストリーム編集、置換、アドレス、ホールドスペース、インプレース変換*

> Source: GNU sed Manual (gnu.org/software/sed) · MIT

## 基本

### sed の実行

```
sed 's/old/new/' file.txt          # 各行の最初のマッチを置換
sed 's/old/new/g' file.txt         # 各行のすべてのマッチを置換
sed -n '5p' file.txt               # 5行目のみ表示
sed '3d' file.txt                  # 3行目を削除
echo "hello" | sed 's/hello/hi/'   # パイプ入力
```

### コマンドラインフラグ

| Command | Description |
|---------|-------------|
| `-n` | 自動出力を抑制。`p` でのみ出力 |
| `-e 'cmd'` | sed コマンドを実行（`-e` を複数連ねて使用） |
| `-f script.sed` | ファイルからコマンドを読み込む |
| `-i[suffix]` | ファイルを直接編集（オプションでバックアップ接尾辞） |
| `-E / -r` | 拡張正規表現を使用 |

## 置換

### 置換構文

```
sed 's/foo/bar/' f                 # 各行の最初の出現を置換
sed 's/foo/bar/g' f                # すべての出現を置換
sed 's/foo/bar/3' f                # 3番目の出現のみ置換
sed 's/foo/bar/gi' f               # すべて大文字小文字を区別せず置換
sed 's|/usr/bin|/opt/bin|g' f      # 代替デリミタを使用
```

### 置換フラグ

| Command | Description |
|---------|-------------|
| `g` | 行内のすべての出現を置換 |
| `N (数値)` | N番目の出現のみ置換 |
| `p` | 置換が行われた場合に行を出力 |
| `w file` | 置換された行をファイルに書き込む |
| `i / I` | 大文字小文字を区別しないマッチ（GNU） |

## アドレス

### アドレス指定の例

```
sed '3s/a/b/' f                    # 3行目のみ
sed '2,5s/a/b/' f                  # 2行目から5行目
sed '/^#/d' f                      # # で始まる行を削除
sed '/start/,/end/d' f             # パターン間の範囲を削除
sed '1~2d' f                       # 奇数行を削除（GNU）
```

### アドレスの種類

| Command | Description |
|---------|-------------|
| `N` | 行番号 N |
| `$` | 最終行 |
| `N,M` | N行目から M行目の範囲 |
| `/regex/` | 正規表現にマッチする行 |
| `/regex1/,/regex2/` | 最初のマッチから2番目のマッチまでの範囲 |
| `N~step` | N から始まり step 行おきの行（GNU） |
| `addr!` | 否定 — マッチしない行に適用 |

## 削除と出力

### 削除と出力コマンド

```
sed '5d' f                         # 5行目を削除
sed '/^$/d' f                      # 空行を削除
sed -n '10,20p' f                  # 10〜20行目を出力
sed -n '/error/p' f                # パターンにマッチする行を出力
sed '/debug/!d' f                  # マッチする行のみ保持
```

### コマンドリファレンス

| Command | Description |
|---------|-------------|
| `d` | パターンスペースを削除して次のサイクルへ |
| `D` | パターンスペースの最初の改行まで削除 |
| `p` | パターンスペースを出力 |
| `P` | パターンスペースの最初の改行まで出力 |
| `q` | 現在のパターンスペースを出力して終了 |
| `Q` | 出力せずに終了（GNU） |

## 挿入と追加

### 挿入・追加・変更

```
sed '3i\inserted line' f           # 3行目の前に挿入
sed '3a\appended line' f           # 3行目の後に追加
sed '3c\replaced line' f           # 3行目を置き換え
sed '/marker/a\new line' f         # パターンマッチの後に追加
```

### コマンド

| Command | Description |
|---------|-------------|
| `i\text` | 現在の行の前にテキストを挿入 |
| `a\text` | 現在の行の後にテキストを追加 |
| `c\text` | 現在の行をテキストで置き換え |
| `r file` | ファイルの内容を読み込んで追加 |
| `R file` | ファイルから1行を読み込んで追加（GNU） |
| `w file` | パターンスペースをファイルに書き込む |

## ホールドスペース

### ホールドスペースコマンド

| Command | Description |
|---------|-------------|
| `h` | パターンスペースをホールドスペースにコピー |
| `H` | パターンスペースをホールドスペースに追加 |
| `g` | ホールドスペースをパターンスペースにコピー |
| `G` | ホールドスペースをパターンスペースに追加 |
| `x` | パターンスペースとホールドスペースを交換 |

### ホールドスペースの使用例

```
sed -n '1!G;h;$p' f               # 行を逆順にする（tac）
sed '/^$/{ x; s/\n//; x; }' f     # 空行でホールドを折りたたむ
sed -n 'H;${x;s/\n/ /g;p;}' f     # すべての行をスペースで結合
```

## 複数コマンド

### コマンドの連鎖

```
sed -e 's/foo/bar/g' -e 's/baz/qux/g' f
sed 's/foo/bar/g; s/baz/qux/g' f
sed '/header/{ s/old/new/; s/foo/bar/; }' f
sed -f commands.sed input.txt
```

### グループ化とブランチ

| Command | Description |
|---------|-------------|
| `{ cmd1; cmd2; }` | 同じアドレスに対してコマンドをグループ化 |
| `:label` | ブランチラベルを定義 |
| `b label` | ラベルへジャンプ（分岐） |
| `t label` | 直前の `s///` が成功した場合にジャンプ |
| `T label` | 直前の `s///` が失敗した場合にジャンプ（GNU） |

## インプレース編集

### インプレース編集の例

```
sed -i 's/old/new/g' file.txt            # 直接編集（GNU）
sed -i.bak 's/old/new/g' file.txt        # file.txt.bak としてバックアップ
sed -i '' 's/old/new/g' file.txt         # macOS インプレース（バックアップなし）
sed -i '/^#/d' config.txt                # コメントをインプレースで削除
```

### プラットフォームの注意

| Command | Description |
|---------|-------------|
| `GNU sed -i` | 接尾辞は任意。`-i` のみでバックアップなし編集 |
| `BSD/macOS sed -i` | 接尾辞引数が必要。バックアップなしは `-i ''` |
| `-i.bak` | `.bak` 拡張子でバックアップファイルを作成 |
| `複数ファイル` | `sed -i 's/a/b/g' *.txt` でマッチするすべてを編集 |

## 正規表現

### sed における正規表現

| Command | Description |
|---------|-------------|
| `.` | 任意の1文字 |
| `*` | 直前の0回以上の繰り返し |
| `\+` | 1回以上（BRE）— ERE では `+` |
| `\?` | 0回または1回（BRE）— ERE では `?` |
| `^` | 行頭 |
| `$` | 行末 |
| `[abc]` | 文字クラス |
| `\( \)` | キャプチャグループ（BRE）— ERE では `()` |
| `\1, \2` | キャプチャグループへの後方参照 |
| `&` | マッチした文字列全体（置換内で使用） |

### 正規表現の例

```
sed 's/[0-9]\+/NUM/g' f               # 数値を置換
sed -E 's/(foo)(bar)/\2\1/g' f         # グループを入れ替え（ERE）
sed 's/.*/(&)/' f                      # 行を括弧で囲む
sed 's/[ \t]*$//' f                    # 末尾の空白を削除
```

## よく使うパターン

### ワンライナー

```
sed -n '1p' f                          # 最初の行（head -1）
sed '$!d' f                            # 最後の行（tail -1）
sed '/^$/d' f                          # 空行を削除
sed 's/^[ \t]*//' f                    # 先頭の空白を削除
sed '=' f | sed 'N;s/\n/\t/' f         # 行番号を付ける
```

### レシピ

| Command | Description |
|---------|-------------|
| `行間を空ける` | `sed G` — 各行の後に空行を追加 |
| `HTML タグを削除` | `sed 's/<[^>]*>//g'` |
| `メールを抽出` | `sed -nE 's/.*([a-z]+@[a-z.]+).*/\1/p'` |
| `行をコメントアウト` | `sed 's/^/# /'` — 各行の先頭に `# ` を追加 |
| `末尾の空行を削除` | `sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'` |
| `N行目を置き換え` | `sed 'Nc\new text'` — N行目を置き換え |
