sedの使い方
sed
コマンドについて確認した。
sed
は「Stream EDitor」のことで、Streamはfileやpipe, stdinをさす。
実行環境はmac OSである。mac OSのsed
はBSD系のコマンドである。
man sed
で確認してみる。
The sed utility reads the specified files, or the standard input if no files are specified, modifying the input as specified by a list of commands. The input is then written to the standard output.
「指定されたファイルか標準入力を受けつけ、入力を変更する」というコマンドである。
sedとawkの使い分け
awk
はaction部分でプログラミングができる。そのため条件分岐などの制御構文が利用可能であり、高機能である。
簡易なテキスト変換はsedで行い、それ以上の複雑な処理がある場合はawkを使うといい。
基本的な使い方
sed1.txt
というファイルを用意する。
xf
hello hello
hello2 hello2
基本的な使い方は以下である。
sed -e s/置換前の文字列/置換後の文字列/ ファイル名
例えば、hello
をworld
に変換するのは以下。
sed s/hello/world/ sed1.txt
出力
world hello
world2 hello2
この出力は、sed1.txt
を書き換える訳ではなく、標準出力として表示されるだけである。
sed
はdefaultでは全ての行を出力する。
また、出力上では、各行で最初に出現するhello
のみ変更されている。
s/置換前の文字列/置換後の文字列/
における/
はdelimiterと呼ばれる。
このdelimiterは/
以外に:
と_
、|
、,
も使うことができる。
sed 's_hello_world_' sed1.txt
sed 's:hello:world:g' sed1.txt
sed 's|hello|world|g' sed1.txt
sed 's,hello,world,' sed1.txt
出力
world world
world2 world2
異なるdelimiterを使うと可読性が上がる。(https://en.wikipedia.org/wiki/Leaning_toothpick_syndrome#Sed)
またパターンマッチ部分は複数定義できる。
echo 'hello world' | sed 's/hello/Hello/; s/world/World/'
// Hello World
行内でパターンマッチした全てのテキストを変更する
パターンマッチ時に/g
と指定することで、global replacementを行うことができる。
sed s/hello/world/g sed1.txt
world world
world2 world2
変更した行だけ表示する
オプションなしだと、パターンマッチが発生してない行も標準出力に含まれる。
sed s/2/world/ sed1.txt
出力
hello hello
helloworld hello2
-n
とp
を使うことで、変更された行のみを表示できる。
sed -n s/2/world/p sed1.txt
helloworld hello2
k番目に出現した文字だけ変更する
/k(kは出現番号)
とすることで、実現できる
echo hoge hoge hoge hoge | sed s/hoge/fuga/2
// hoge fuga hoge hoge
行番号を指定して変更する
2~4行目で、文字列変換をする。
echo "hello\nhello\nhello\nhello" | sed '2,4s/hello/world/'
/*
hello
world
world
hello
*/
2行目から最終行まで変換。
echo "hello\nhello\nhello\nhello" | sed '2,$s/hello/world/'
行番号を指定して削除
echo "hello1\nhello2\nhello3\nhello4" | sed 2d
/*
hello1
hello3
hello4
*/
echo "hello1\nhello2\nhello3\nhello4" | sed 2,4d
// hello1
パターンマッチをして含む行を削除
echo "hello1\nhello2\nhello3\nhello4\nhello5" | sed '/hello2/,/hello4/d'
/*
hello1
hello5
*/
出力を別ファイルに書き出す
/w <ファイル名>
とすることで、変換後の内容を指定するファイル名に書き出すことができる。
sed 's/hello/world/w sed1_output.txt' sed1.txt
パターンマッチした文字列を複製させる
パターンマッチした文字列は&
に格納できる。これを複数並べることで、パターンマッチした文字列を複数回数表示することができる。
echo "123 abc" | sed 's/[0-9]*/& &/'
// 123 123 abc
echo "123 abc" | sed 's/[a-z].*/& &/'
//123 abc abc
行数を表示
echo "hello1\nhello2\nhello3\nhello4\nhello5" | sed '='
1
hello1
2
hello2
3
hello3
4
hello4
5
hello5
ある文字列を含む行のみで、文字列置換
fuga
を含む行で、aをbに置換。
echo "1hogeaaa\n2fugaaaa" | sed '/fuga/s/a/b/g'
/*
1hogeaaa
2fugbbbb
*/
シングルクォートで囲んでもいい
正規表現のパターンマッチの部分はクォートで囲んでもいい。
sed 's/hello/world/g' sed1.txt
はクォートがない場合と同じ挙動である。
エスケープ
(
と)
で囲まれた文字をパターンマッチし、変換したい。
echo "(123) (aa)" | sed -E 's/([1-9]+)/hoge/'
// (hoge) (aa)
この場合 バックスラッシュ\
を利用することで実現できる。
echo "(123) (aa)" | sed -E 's/\([1-9]+\)/hoge/'
// hoge (aa)
extended regular expression
BSD系のsed
ではオプション-E
をつけることで、basic regular expressionからextended regular expressionへ切り替えることができる。
+
や?
が使用可能になる。
echo "123 abc" | sed -E 's/[a-z]+/& &/'
//123 abc abc
- https://entree.hatenadiary.org/entry/20141126/1417016871
- https://murashun.jp/article/programming/regular-expression.html
Back Reference
「後方参照」と呼ばれるもので、以下のようなもの。
これは、 条件内で「(」「)」で後方参照したい箇所を囲むことで、囲った個所を前から順に「\1」「\2」で参照するもの。
echo 'abcdef' | sed -e 's/\(...\)\(...\)/\2\1/g'
// defabc
echo "James Bond" | sed -E 's/(.*) (.*)/The name is \2, \1 \2./'
// The name is Bond, James Bond.
BSD版のsedでは大文字、小文字の変換ができない。
GNU版のsed: https://www.gnu.org/software/sed/manual/sed.html
Finally, as a GNU sed extension, you can include a special sequence made of a backslash and one of the letters L, l, U, u, or E. The meaning is as follows:(略)
\L
等を使い、アルファベットの大文字小文字の変換が可能。
BSD版のsed: https://www.freebsd.org/cgi/man.cgi?query=sed&sektion=&n=1
できない。
例
echo "(a)\n(b)\n(c)" | sed 's/^\(.\)\(.\)\(.\)/\3\2\1/'
/*
)a(
)b(
)c(
*/
echo "asdf@gmail.com" | sed 's!@[a-z].*!!'
// asdf
mac OSにはなぜBSD系コマンドが採用されているか
- Mac OSの前身となるOSは、NeXTで開発され、それはBSD系のOSであるMach OS(マークOS、マイクロカーネル方式)を改良して作られた。
- AppleはNeXTのユーザーインターフェイスをMacintoshユーザーフェイスに置き換えた。
- Appleは徐々にNeXTのモジュールを減らし、BSDの素のモジュールとAppleで開発したモジュールで置き換えるようにしている。
- Mach OSのマイクロカーネルも、AppleのXNU hybrid kernelで置き換えられた。macOS Catalina 10.15にはNeXTのモジュールは残っておらず、BSDのソフトウェアコンポーネントと、Appleの独自のコンポーネントから成る。
なお、
参考
- https://www.quora.com/Is-macOS-considered-to-be-a-BSD-UNIX
- https://ja.wikipedia.org/wiki/Mach
- https://github.com/apple/darwin-xnu
GNUのsed
参考
- http://psa2.kuciv.kyoto-u.ac.jp/staff/susaki/command/c_sed.html
- https://www.grymoire.com/Unix/Sed.html
- https://stackoverflow.com/questions/1632113/what-is-the-difference-between-sed-and-awk
- https://orebibou.com/ja/home/201507/20150731_001/
- http://sed.sourceforge.net/sedfaq3.html
正規表現可視化
Discussion
BSD sed と GNU sed には多数の非互換がありますが, 個人的に一番つらいと感じるのは
-i
オプションの非互換ですね…(調べてみてください)この点があるので, in-place で置換したいときは Perl 1 択かなぁとなっております…