シェルスクリプトからテキストファイルの編集をする場合は sed(1) や awk(1) を利用して編集結果を一時ファイルに出力し、編集後に mv(1) などでリネームする処理が一般的だと思います(一部バージョンの sed(1) には対象ファイルを直接編集する機能が実装されているものもありますが、これは拡張機能なので必ず使える訳ではないので除外します)。
この方法でも勿論問題ないのですが ex(1) を利用すると対象となるファイルを直接編集できるので便利な場合もあります。
ex(1) は実は vi(1) そのものなので vi(1) で利用できる強力な編集機能がフルで利用できる事も ex(1) を利用するメリットの一つです。
ex(1) を利用してファイルを編集する場合は編集コマンドをヒアドキュメントで ex(1) に通知するのが判りやすくて良いと思います。
ヒアドキュメントのデリミタ直前の - はヒアドキュメントテキストの行頭のタブを無視する指定です。
ファイルへの行追加
ex(1) の a コマンドで追加モードにしてコンテンツを追加して . コマンドで追加モードを終了、w! でファイルに出力して終了します。
# $1: 編集対象ファイル名
# $2: 追加する行番号
# $3: 追加するコンテンツ
addline()
{
/bin/ex -s ${1} <<- EOF
${2}a
${3}
.
w!
EOF
}
ファイルの行削除
ex(1) の d コマンドで指定した行を削除して w! でファイルに出力して終了します。
# $1: 編集対象ファイル名
# $2: 削除する行番号
delline()
{
/bin/ex -s ${1} <<- EOF
${2}d
w!
EOF
}
行番号を指定したファイルの行置換
ex(1) の c コマンドで指定した行を置換して w! でファイルに出力して終了します。
# $1: 編集対象ファイル名
# $2: 置換する行番号
# $3: 追加するコンテンツ
chgline()
{
/bin/ex -s ${1} <<- EOF
${2}s/.*/${3}/
w!
EOF
}
パターンを指定したファイルの行置換
ex(1) の c コマンドで最初に見付かったパターンを置換して w! でファイルに出力して終了します。
sの後ろの連続した // は直前の正規表現(パターンを指定した正規表現)を示します。
# $1: 編集対象ファイル名
# $2: 置換するパターン
# $3: 追加するコンテンツ
chgline()
{
/bin/ex -s ${1} <<- EOF
/${2}/s//${3}/
w!
EOF
}
これらの処理はあくまでも動作サンプルを示しただけですので、実際にスクリプトに利用する場合にはエラー処理や例外処理などが必要になります(どんなスクリプトでも同じですが)。例えば、置換処理では置換する/置換される文字列に / を含む事ができないので、/ が含まれる場合は正規表現デリミタを別な文字に置き換える必要があります。
スクリプトでも解法は沢山ありどれが絶対的な正解だという方法はありません。こういう方法もあるという事を覚えておくと役に立つ場合があるかもしれません。