sed

スクロール: トップ

アドレスとは

アドレス未指定

アドレス1個

アドレス2個: アドレス範囲

アドレスの反転

行指定アドレス

正規表現アドレス

拡張正規表現

アドレスの入れ子

アドレス

  • 行指定アドレス、正規表現アドレス
  • アドレスの入れ子

更新


アドレスとは

他のコマンド | sed オプション 'アドレス コマンド;'

コマンドを適用するか決める条件

複数のsedスクリプトの場合

  • sedスクリプトは、複数の「アドレス コマンド;」が連なることがある
  • 並んでいる順番に意味がある
正規表現アドレス1 コマンド1
正規表現アドレス2 コマンド2

コマンド1でパターンスペースが変化した場合、変化後のパターンスペースにアドレス2がマッチしたら、コマンド2を適用。

  • 行指定アドレスは、パターンスペースの元になった入力行の行番号にマッチするかどうか

アドレスの数

  • アドレス未指定のときは、必ずコマンド適用
  • アドレス範囲:
    • 開始・終了のアドレスを2個指定し、その範囲でコマンド適用
  • アドレスを直接は使えないのがラベル

アドレスに関係なく、パターンスペースにコピー

  • アドレスは、入力行をパターンスペースにコピーするかを決める条件ではない
  • 入力は、とにかくパターンスペースにコピーされる

例: 1 =; 2 p;

上記12が行指定アドレス、=pがコマンドの、複数スクリプトの例。

まず、入力1行目がパターンスペースにコピー

  1. アドレス1はマッチするので、=を適用
  2. 2 pは当てはまらない

入力1行目の処理が終わり、

次に、入力2行目がパターンスペースにコピー

  1. 1 =は当てはまらない
  2. アドレス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個: アドレス範囲

書式: 開始アドレス,終了アドレス コマンド

  • 開始アドレスにマッチしてから、終了アドレスにマッチするまでの間、コマンド適用
  • スクリプトを終了するqQコマンドでは使用不可
input='1行目
2行目
3行目'
echo "$input" | sed '1,2 ='
1
1行目
2
2行目
3行目

アドレスの反転

  • コマンドの直前に!を置くと、アドレスがマッチしないときにコマンドを適用

アドレス ! コマンド

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"
ストロベリージュース
ショートケーキ
きいちごケーキ
いちごパフェ

https://memo.open-code.club