sedは、スクリプト型言語の1種です。シェルスクリプトに含まれる1機能だと誤解されがちですが、sed単体で1つの言語となります。

ただ、現実にはシェルスクリプトの中で「パターンに一致した文字列を、別の文字列に置き換える」ときに利用されることが多く、sed単体で何かをやるということはあまり見かけないように思えます。

今回は、sedを使用した文字列置換のサンプルを作成します。

#!/bin/bash
read in
echo "$in" | sed 's/abc/123/'
echo "$in" | sed 's/abc/123/g'

実行結果 abcと入力した場合

123
123

実行結果 abcabcと入力した場合

123abc
123123

実行結果 23456と入力した場合

23456
23456

sedで最も利用されるのがsコマンドです。sコマンドは「パターンに一致した文字列を、別の文字列に置き換える」機能を持ちます。パターンには正規表現も使用できます。

sコマンドの基本形
sed ‘s/パターン/文字列/’   パターンに一致した最初の1つだけを置き換え
sed ‘s/パターン/文字列/g’   パターンに一致した部分すべてを置き換え

打消し文字の利用

例えば、「/bin/sh」という文字列を「/bin/bash」に置き換えたいとします。その場合、上記したsコマンドの基本形に従うと以下のような書き方になるように思えます。

sed 's//bin/sh//bin/bash'/

しかし、このsedコマンドを実行してもエラーとなります。それは「/」が特殊文字だからです。特殊文字を単なる文字として扱いたい場合は「/」をバックスラッシュ「\」で打ち消す(エスケープする)必要があります。
それを踏まえ、以下のように書き直してみます。

sed 's/\/bin\/sh/\/bin\/bash'/

「\」や「/」がたくさんでてきて混乱しそうですが、パターンと文字列を区切る「/」とパターンや文字列に含まれる「/」を落ち着いて見きわめ、パターンや文字列に含まれる「/」の前に「\」を置いてやるということを理解していれば、難しいことではありません。※バックスラッシュは日本語キーボードでは「¥」になりますが、意味は同じです。

sedの区切り文字を変更する

上記例のように、sedで扱うパターンや文字列の中にスラッシュが入るとややこしい記述となります。そのようなときは、区切り文字をスラッシュではない文字に変更することもできます。区切り文字はスラッシュで決まっているわけではなく、何を指定しても構いません。

例えば、

s/\/bin\/sh/\/bin\/bash/

の区切り文字を%に変更して、

s%/bin/sh%/bin/bash%

と、することも可能です。この場合はスラッシュは区切り文字ではないため、打ち消す必要はありません。

ただ、慣習としてスラッシュを使っていることがほとんどで、スラッシュ以外の文字を区切り文字として使うと、混乱を招くことになりかねないので、多用は厳禁です。

正規表現の後方参照

sedコマンドにより、様々な文字列置換を行えます。以下は年号を4桁から2桁に変更する例です。

read in
echo "$in" | sed 's/\([0-9][0-9]\)\([0-9][0-9]\)/\2/g'

いろいろな記号が出てきてわけが分からないようですが、このような場合は、分かるところからひとつずつ考えていきます。

sコマンドの基本形は、

sed 's/パターン/文字列/g'

です。この基本形に照らし合わせると、

s/\([0-9][0-9]\)\([0-9][0-9]\)/\2/g

と、なります。

まず、パターンについて、このままではわかりにくいので打ち消し文字を除外してみます。

パターン ([0-9][0-9])([0-9][0-9])

パターンとしては数字が4つ連続しているという意味です。そのうち、最初の2つと最後の2つが、それぞれカッコで囲まれています。
カッコで囲まれた部分は特殊な意味を持ち、最初のカッコで囲まれた部分を\1、第2のカッコで囲まれた部分を\2と表します。つまり、置換する文字列として\2と指定した場合、この例では4つの数字のうち最後の2つという意味になります。

こられを踏まえ、そのsedコマンドの意味は「数字が4つ連続する文字列を、最後の2つの数字に置き換える」となります。
つまり、入力する文字列が2018であれば、下2桁である18に置き換えられます。