アドレス
- 行指定アドレス、正規表現アドレス
- アドレスの入れ子
更新
アドレスとは
他のコマンド | sed オプション 'アドレス コマンド;'
コマンドを適用するか決める条件
- 現在のパターンスペースについて、アドレスがマッチしたら、コマンド適用
複数のsedスクリプトの場合
- sedスクリプトは、複数の「
アドレス コマンド;」が連なることがある - 並んでいる順番に意味がある
正規表現アドレス1 コマンド1
正規表現アドレス2 コマンド2
コマンド1でパターンスペースが変化した場合、変化後のパターンスペースにアドレス2がマッチしたら、コマンド2を適用。
- 行指定アドレスは、パターンスペースの元になった入力行の行番号にマッチするかどうか
アドレスの数
アドレスに関係なく、パターンスペースにコピー
- アドレスは、入力行をパターンスペースにコピーするかを決める条件ではない
- 入力は、とにかくパターンスペースにコピーされる
例: 1 =; 2 p;
上記1や2が行指定アドレス、=やpがコマンドの、複数スクリプトの例。
まず、入力1行目がパターンスペースにコピー
- アドレス
1はマッチするので、=を適用 2 pは当てはまらない
入力1行目の処理が終わり、
次に、入力2行目がパターンスペースにコピー
1 =は当てはまらない- アドレス
2はマッチするので、pを適用
アドレス未指定
書式: コマンド
- すべての入力行のサイクルでコマンド適用
input='1行目
2行目
3行目'
echo "$input" | sed '='
1
1行目
2
2行目
3
3行目
=コマンドは、現在のパターンスペースの元である入力の行番号を出力- 別途、「サイクル末ごとの自動出力」もあり
アドレス1個
書式: アドレス コマンド
- アドレスにマッチした場合のみ、コマンド適用
- 一部のコマンドはパターンスペースを変化させる
- アドレスとコマンド間のスペースはなくてもよい (以降同様)
input='1行目
2行目
3行目'
echo "$input" | sed '2 ='
1行目
2
2行目
3行目
- 行指定アドレスの
2により、入力2行目のサイクルだけマッチし、行番号を出力 - 別途、「サイクル末ごとの自動出力」もあり
アドレス2個: アドレス範囲
書式: 開始アドレス,終了アドレス コマンド
- 開始アドレスにマッチしてから、終了アドレスにマッチするまでの間、コマンド適用
- スクリプトを終了する
qとQコマンドでは使用不可
input='1行目
2行目
3行目'
echo "$input" | sed '1,2 ='
1
1行目
2
2行目
3行目
- 行指定アドレスの
1から2までの間、行番号を出力 - 別途、「サイクル末ごとの自動出力」もあり
アドレスの反転
- コマンドの直前に
!を置くと、アドレスがマッチしないときにコマンドを適用
アドレス ! コマンド
input='1行目
2行目
3行目'
echo "$input" | sed '2 ! ='
1
1行目
2行目
3
3行目
開始アドレス,終了アドレス ! コマンド
input='1行目
2行目
3行目'
echo "$input" | sed '1,2 ! ='
1行目
2行目
3
3行目
行指定アドレス
| 書式 | 例 | 意味 |
|---|---|---|
| 行番号 | 3 |
3行目 |
| 行番号 ! | 3 ! |
3行目以外 |
| 開始行,終了行 | 3,5 |
3〜5行目 |
| 開始行~間隔 | 3~5 |
3、3+5、3+10のように5行間隔1~2で奇数行、2~2で偶数行 |
| $ | $ |
最終行3,$なら3行目から最終行まで |
| 開始行,+行数 | 2,+3 |
2行目から5行目まで |
| 開始行,+行数 ! | 2,+3 ! |
「2行目から5行目まで」以外 |
以下、パターンスペースを削除するdコマンドを例にすると、
~n: ステップ(n行ごとに適用)
奇数行を削除
seq 1 5 | sed '1~2 d'
2
4
最終行$
seq 1 999 | sed '2,$ d'
1
+n行
seq 1 4 | sed '2,+1 d'
1
4
正規表現アドレス
| 書式 | 例 | 意味 |
|---|---|---|
| /正規表現/ | /abc/ |
abcを含む行 |
| /正規表現/ ! | /abc/ ! |
abcを含まない行 |
| \%正規表現% | \%^/home/% |
/home/から始まる行 区切りを /から%に変更した例 |
| 行番号,/正規表現/ | 3,/^abc$/ |
3行目から最初のabc行まで |
| /正規表現/,+行数 | /^abc$/,+5 |
abc行と追加で5行まで 複数範囲可能 |
| /正規表現/,/正規表現/ | /^abc$/,/^efg$/ |
abc行からefg行まで 複数範囲可能 |
input='
りんごジュース
みかんジュース
いちごケーキ'
echo "$input" | sed '/ケーキ/ ! d'
いちごケーキ
正規表現の区切りを変更
/正規表現/ => \%正規表現%など
- 特に正規表現自体に
/を含んで見にくいときなど\でエスケープしてもよいが
%の部分は任意の文字でOK
input='/home/alice/temp
/root/temp
/home/john/local'
echo "$input" | sed '\%^/home/% d'
echo "$input" | sed '\#^/home/# d'
# エスケープで対応
echo "$input" | sed '/^\/home\// d'
/root/temp
行番号,/正規表現/
- 指定行から正規表現に最初にマッチするまで、コマンド適用
- 正規表現のマッチは指定行の次の行から
- 1行目からマッチ可能にしたいなら、
0,/正規表現/
input='りんごジュース
みかんジュース
いちごケーキ'
echo "$input" | sed '2,/ケーキ/ d'
りんごジュース
echo "$input" | sed '0,/ジュース/ d'
みかんジュース
いちごケーキ
/正規表現/,+行数
- マッチ行と、次の行から行数分
- 複数の範囲にマッチすれば、それぞれコマンド適用
input='# こめんと
echo abc
abc
# コメント
echo xyz
xyz'
echo "$input" | sed '/^#/,+1 d'
abc
xyz
/正規表現/,/正規表現/
- 複数の範囲にマッチすれば、それぞれコマンド適用
input='#
開始
a
b
終了
X
開始
c
終了
Y'
echo "$input" | sed '/開始/,/終了/ d'
#
X
Y
拡張正規表現
デフォルトは基本正規表現
?,+,(),{},|: これらもただの文字扱い
echo '?+(){}|' | sed --quiet '/^?+(){}|$/ p'
?+(){}|
--regexp-extended, -E
echo 'abc' | sed -E --quiet '/^abcd?$/ p'
echo '123333' | sed -E --quiet '/^123+$/ p'
echo 'abcabc' | sed -E --quiet '/^(abc){,2}$/ p'
echo 'xyz
XYZ' | sed -E --quiet '/^(xyz|XYZ)$/ p'
abc
123333
abcabc
xyz
XYZ
他言語の拡張正規表現との違い
- 「マッチしたものを記憶しない(再利用できない)グループ」表現は
sedでは使えない- PerlやJavaScriptなどで使える
(?:マッチ)、(?=マッチ)、(?!マッチ)
grep --perl-regexpでは機能
日本(?!語): 後ろに「語」が付かない「日本」にマッチする
echo '日本語
日本人' | grep --perl-regexp '日本(?!語)'
日本人
sedではエラー
echo '日本語
日本人' | sed -E --quiet '/日本(?!語)/ p'
sed: -e expression #1, char 16: 無効な前方正規表現です
アドレスの入れ子
アドレス { sedスクリプト }
- アドレスによる絞り込みを入れ子にできる
- コマンドのグループ化(ブロック)になる
# 「いちごケーキ」を「ショートケーキ」に変更
# ただし「きいちごケーキ」はそのまま
input='いちごジュース
いちごケーキ
きいちごケーキ
いちごパフェ'
script='
/きいちご/ ! {
/ジュース/ s/いちご/ストロベリー/
/ケーキ/ s/いちご/ショート/
}
'
echo "$input" | sed "$script"
ストロベリージュース
ショートケーキ
きいちごケーキ
いちごパフェ