アドレス
- 行指定アドレス、正規表現アドレス
- アドレスの入れ子
更新
アドレスとは
他のコマンド | 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"
ストロベリージュース
ショートケーキ
きいちごケーキ
いちごパフェ