第7章:フィルタの使用法

始めに

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界」の第7章は、「フィルタの使用法」となっていますが、ようはsedです。いや、やっとsedですよ、sed。男子たるモノ、sedくらい使えないとどないする?って感じのsedです。もちろん、女子でsedを使えるとかっこいいなぁ。
ってわけで、sedは楽しみなの第7章は楽しくできそうです。ページは25ページほどなのでそんなに大変ではなさそう。

フィルタとは

フィルタとは、標準入力からデータを受け取って、変更を加えて標準出力に書き出す処理のこと。通常は下記にようにパイプ(|)を使って行う。パイプを使えば複数のフィルタも簡単にできる。

cat	file	|
	filter	|
	filter2	|
	while read LINE
	do
		・・・
	done

もし、複数のファイルをいっぺんにフィルタしたければ、並べて書いてパイプで渡す。

cat file1 file2 file3    | filter

下記のようにリダイレクトを使ってもフィルタが可能。

filter1 < file | filter2

sedコマンド

sedコマンドは、標準入力からデータを受け取って、編集後の結果を標準出力に書き出す。この章ではsedを使ってフィルタを練習する。

sedの基本

e、sオプション

sedの-eオプションは、後ろの/に続く文字列が編集用のコマンドと言うことを示す。sは、substitute(置換)の意味で、/の左側の文字列を/の右側の文字列に置き換えると言う意味になる。下記の例だと、ファイルの中の「OldText」と言う文字列を「NewText」と言う文字列に置き換えるとなる。

$ sed -e "s/OldText/NewText/" ファイル
gオプション

上記の例だと、1行に2つ以上の「OldText」と言う文字列があった場合、最初の「OldText」しか置換しない。もし、1行で複数の置換を行いたい場合は最後の/の後にg(global)をつける。

$ sed -e "s/OldText/NewText/g" ファイル
変数を使用した編集

変数を使用した処理も可能。

$ OLDTEXT=OldText
$ NEWTEXT=NewText
$ sed -e "s/$OLDTEXT/$NEWTEXT/" ファイル

-n,pオプション
sedは、デフォルトで処理した行も処理しなかった行の両方を出力する。もし、処理した行を出力したい場合は-nオプションを使用する。注意事項として、-nを使用した場合、「出力しなさい」と言う意味の-pオプションも必ず一緒に使用しなければならない。-nの意味は、本当は指定した行だけを出力しないさという意味になる。なので、下記の例だと2行目だけ出力するという意味になる。(編集してなくても)

$ sed -n '2p' < ファイル

編集した行だけ出力させたければ下記のようにする。

sed -n -e "s/OldText/NewText/gp" ファイル

パイプを使ったsedの処理

リダイレクト等で処理を行うと、何度もsedで編集する場合、中間ファイルができてしまう。そこで中間ファイルを作りたくない場合はパイプを利用する。例としては以下の通り。下記のようにパイプで渡していけば、何回でも編集が可能になる。

sed -e "s/Old_1/New_1/g" | sed -e "s/Old_2/New_2/g" | 

デリミタ(/)の変更

文字列を区切ってる/をデリミタと呼ぶ。もし、/をしたい場合は\等でエスケープしてもいいが、それだと可視性がよくないのであまり推奨されない。そこで、デリミタに/を使用するが、本当は何でもいいので、%や@をデリミタに使用することもある。

文字の変換

置換はsを使用する。g(global)がない場合は行の最初にマッチしたものだけ置換する。

sed -e "s/置換前/置換後/g"

文字の削除

sedを使って文字の削除も可能。置換の機能を利用して、何もない文字に変換すると言うやり方。

sed -e "s/置換前//g"

行の先頭の文字列を消す

指定した文字列が行の先頭にあったときだけ、その文字を削除する。^が「行の最初」を表す。

sed -e "s/^置換前//"

行末の文字を消す

今度は行の最後に指定した文字があれば、その文字を削除する。$が「行の最後」を表す。注意事項として$はシェルの特殊文字なので、sedより先にシェルに解釈させるとまずいので\をつけてエスケープさせる必要がある。

sed -e "s/置換前\$//"

文字列の追加

文字の追加は、基本的には行の最初や行の最後しかできない。もし、文中に追加したい場合は下記のように置換の延長で行う。

sed -e "s/abc/abcxyz/g/"

行の先頭に文字を追加

^を使って行の先頭に文字を追加できる。

sed -e "s/^/追加したい文字列/"

行の最後の文字を追加

上記と同じ。単に$を使うだけ。$なので、エスケープも同じ。

sed -e "s/\S/追加したい文字列/"

ドット(.)とアスタリスク(*)

任意の文字列を削除や編集したいときにはドットやアスタリスクを使用する。

  • ドットは任意の1文字を示す。
    • 1文字であれば.
    • 4文字であれば....
  • アスタリスクは、直前の文字が任意の個数連続したことを示す(0回も含む)
    • aで始まる文字を表すときはa*(aだけも含む)

先頭の3文字を無条件で削除するときの例

sed -e "s/^...//"

.*とすると、すべてとなるので、すべての行をabcに置き換える例は書きの通り。

sed -e "s/.*/abc/"

スラッシュ(/)以外のデリミタ

例えば、abc/def/ghiの文字列で、最初の/以降の文字を切り落としたい場合、スラッシュ以外を使う。例としては%を使用。

sed -e "s%/.*%%"

sed以外での切り落とし

切り落とす文字数がわかってないときには.*を使わないといけないが、もし何文字目を切り落とすかわかっているのであれば、cutコマンドやawkコマンドを使用する。例としてcutコマンドにて最初(1文字目)から5文字目までを切り落とすサンプルを表示する。awkはまたいつか。。。

echo "$STRING" | cut -c1-5

大文字小文字の入れ替え

大文字と小文字の変換にはtrコマンドを使用する。以下に指定したファイルの大文字を小文字に変更するサンプルを記載する。

$ cat ファイル  | tr '[A-Z]' '[a-z] > 変更後のデータ格納ファイル

タブをスペースに変換

単にタブとスペースを指定すればいいだけ。

sed -e "s/<tab>/<space>/g"

複数のスペースを1つのスペースにマージ

複数のスペースを指定するには*で表現できるので、あとは同じ。気をつけないといけないのは、*で指定するとスペースなしも含まれてしまうので、*としてスペースを2つ指定するべし。以下にサンプルを記載。

sed -e 's/<space><space>*/<space>/g'

ホワイトスペースを1つのスペースへ変換

始めて聞きましたが、ホワイトスペースとはタブかスペースのことを言うそうです。ようするにタブとスペースの混在ですな。そんな混在しているものを1つのスペースに統一するときのやり方を下に記載。[]を使うことで、どちらかと言う表現が可能なので、下の例だとなどがマッチする。

sed -e 's/[<space><tab>][<space><tab>]*/<space>/g'

先頭のホワイトスペースを削除

シングルクォートの場合

sed -e 's/[<space><tab>]*$//'

もしダブルクォートを使用する場合は、$をエスケープする必要がある

sed -e "s/[<space><tab>]*\$//"

指定した文字列を含んだ行を削除

削除の場合、先頭のsが不要になる(sは変換するときに必要なだけ)。最後のdが削除を示す。

sed -e "/文字列/d"

同じことをgrepコマンドでも可能。grepコマンドで-vオプションを使用すると「該当する文字列を含んだ行は表示しない」となる。

grep -v "文字列"

空白行の削除

下記の例は、改行コードのみの行を削除。もしスペースやタブだけの行を削除したければ、さらに下のサンプルを参照

sed -e '/^$/d'

タブやスペースだけの行も削除

sed -e '/^[<space><tab>]*$/d]'

sedによる行の指定

sedは、対象とする行を指定することも可能。以下に5行目から10行目のみ処理を当てたいときのサンプルを記載する。

sed -e "5,10s/置換前/置換後/g" ファイル

もし、指定した行から最後までとかを指定したい場合には$を使用する。$は最終行を表す。下記は5行目から最終行までのサンプル。もし、ダブルクォートでくくる場合は$のクォートを忘れないように。

sed -e '5,$s/置換前/置換後/g' ファイル

行の削除

先ほどの方法を使って行の削除も可能。1行目から4行目の削除のサンプル。

sed -e '1,4d' ファイル

最後の4行を削除するサンプル

sed -e '$-3,$d' ファイル

指定した行だけの表示

nオプションをつければ可能(nオプションは処理した行だけ表示するという意味)。nオプションを使用するときはpオプションも忘れずに。1行目だけを表示するサンプル。

sed -n '1p' ファイル

もしn行目からm行目までの場合は以下の通り。

sed -n 'n,mp' ファイル

キーワードによる行の指定

sedで処理するときに対象を行で指定することもできるが、キーワードで指定することも可能。例えば、下記の例だとBeginと言う文字列からEndと言う文字列の間っていう指定を行う。

sed -e "/Begin/,/End/d" ファイル

もし、指定するキーワードのみの行となっているのであれば、下記の例がいいそうだ。

sed -n "/^Begin\$/,/^End\$/p" ファイル

ファイルを後ろから表示

grepの-nオプションを使って先頭に番号をつけ、sortコマンドで並び替える。最後にsedで行番号を削る。以下にサンプルを掲載。

$ cat ファイル | grep -n '.*' | sort -n -r | sed 's/^[0-9]*://'

終わりに

1つ1つ確認していったので、思いのほか時間がかかりましたが、しっかり理解するには実際に1つ1つ試していくのがいいかと思いまする。あとは、実際に使おうと思ったときに思いつくかどうかっすね。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界