Bashプログラミング
 Computer >> コンピューター >  >> プログラミング >> Bashプログラミング

sedの高度な置換テクニック:区切り文字・「&」・後方参照を実践例でマスター

本記事は、「Unix Sed Tips and Tricks」シリーズの一環としてお届けします。

これまでのsed関連記事では、sedによる出力(print)、削除(delete)、置換(substitute)、ファイルへの書き出し、複数コマンドの組み合わせなどを学んできました。

今回は、sedの「s」置換コマンドを使った実用的かつ興味深いテクニックを、具体的なサンプルを交えて詳しく解説していきます。

1. sed置換における区切り文字

以前の記事でも触れたとおり、sedの置換コマンドでは、@、%、|、;、: など、さまざまな記号を区切り文字として利用できます。

まず、以降のすべての例で使用する path.txt ファイルを作成しておきましょう。

$ cat path.txt
/usr/kbos/bin:/usr/local/bin:/usr/jbin:/usr/bin:/usr/sas/bin
/usr/local/sbin:/sbin:/bin/:/usr/sbin:/usr/bin:/opt/omni/bin:
/opt/omni/lbin:/opt/omni/sbin:/root/bin

例1:@ を区切り文字に使う ― /opt/omni/lbin を /opt/tools/bin に置換

パス名のように「/」を含む文字列を置換する場合、「/」の代わりに「@」を区切り文字にすると読みやすく安全です。次の例では、入力ファイルの最終行にある /opt/omni/lbin が /opt/tools/bin に変更されています。

$ sed 's@/opt/omni/lbin@/opt/tools/bin@g' path.txt
/usr/kbos/bin:/usr/local/bin:/usr/jbin/:/usr/bin:/usr/sas/bin
/usr/local/sbin:/sbin:/bin/:/usr/sbin:/usr/bin:/opt/omni/bin:
/opt/tools/bin:/opt/omni/sbin:/root/bin

例2:標準の「/」を区切り文字に使う ― エスケープが必要なケース

どうしても「/」を区切り文字として使いたい場合は、パターン部分と置換部分の両方で「/」をバックスラッシュ(\)でエスケープする必要があります。以下の例では、REGEXP部分とREPLACEMENT部分それぞれでエスケープを行っています。

$ sed 's/\/opt\/omni\/lbin/\/opt\/tools\/bin/g' path.txt
/usr/kbos/bin:/usr/local/bin:/usr/jbin/:/usr/bin:/usr/sas/bin
/usr/local/sbin:/sbin:/bin/:/usr/sbin:/usr/bin:/opt/omni/bin:
/opt/tools/bin:/opt/omni/sbin:/root/bin

2. 「&」でマッチした文字列を取得する

正規表現が入力行のどの部分にマッチしたかを表す特殊文字が「&」です。この「&」は、置換部分でそのまま再利用できます。

例1:「&」の基本 ― /usr/bin を /usr/bin/local に置換

$ sed 's@/usr/bin@&/local@g' path.txt
/usr/kbos/bin:/usr/local/bin:/usr/jbin/:/usr/bin/local:/usr/sas/bin
/usr/local/sbin:/sbin:/bin/:/usr/sbin:/usr/bin/local:/opt/omni/bin:
/opt/omni/lbin:/opt/omni/sbin:/root/bin

この例では、置換部分の「&」がマッチしたパターン「/usr/bin」に展開され、続けて「/local」が連結されます。その結果、出力ではすべての「/usr/bin」が「/usr/bin/local」へと置き換えられています。

例2:行全体にマッチさせて装飾する

「&」は、指定した正規表現にマッチした内容全体を表します。

$ sed 's@^.*$@<<<&>>>@g' path.txt
<<</usr/kbos/bin:/usr/local/bin:/usr/jbin/:/usr/bin:/usr/sas/bin>>>
<<</usr/local/sbin:/sbin:/bin/:/usr/sbin:/usr/bin:/opt/omni/bin:>>>
<<</opt/omni/lbin:/opt/omni/sbin:/root/bin>>>

ここでは正規表現「^.*$」が行全体にマッチします。置換部分の「<<<&>>>」によって、各行の先頭に「<<<」、末尾に「>>>」が付加されます。

3. グルーピングと後方参照

sedでは、通常の正規表現と同じようにグルーピングが使えます。グループは「\(」で開き、「\)」で閉じます。グルーピングは、後方参照と組み合わせて使うことで真価を発揮します。

後方参照とは、グループ化して捕捉した正規表現の一部を再利用することです。sedの後方参照は、正規表現本体だけでなく、置換コマンドの置換部分でも使用できます。

例1:各行から最初のパスだけを取り出す

$ sed 's/\(\/[^:]*\).*/\1/g' path.txt
/usr/kbos/bin
/usr/local/sbin
/opt/omni/lbin

この例では、「\(\/[^:]*\)」が最初の「:」より前にあるパス部分にマッチし、「\1」が最初のグループ(マッチしたパス)を参照しています。

例2:複数グループの活用 ― 最終行のフィールド順序を入れ替える

path.txt の最終行にあるフィールドの並び順を逆にしてみましょう。

$ sed '$s@\([^:]*\):\([^:]*\):\([^:]*\)@\3:\2:\1@g' path.txt
/usr/kbos/bin:/usr/local/bin:/usr/jbin:/usr/bin:/usr/sas/bin
/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/omni/bin:
/root/bin:/opt/omni/sbin:/opt/omni/lbin

コマンド冒頭の「$」により、置換処理が最終行だけに限定されます。出力結果を見ると、最終行のパスの順序が反転していることが確認できます。

例3:/etc/passwd からユーザー名の一覧を抽出する

この例では、/etc/passwd ファイルの最初のフィールド(ユーザー名)のみを表示します。

$ sed 's/\([^:]*\).*/\1/' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown

例4:各単語の先頭文字を括弧で囲む

この例では、文中の各単語の1文字目を括弧で囲んで出力します。単語境界「\b」と大文字の文字クラスを組み合わせたテクニックです。

$ echo "Welcome To The Geek Stuff" | sed 's/\b\([A-Z]\)/(\1)/g'
(W)elcome (T)o (T)he (G)eek (S)tuff

例5:数値に桁区切りのカンマを挿入する

数値のリストを含む numbers ファイルを作成し、千の位ごとにカンマを挿入してみましょう。

$ cat numbers
1234
12121
3434
123
$ sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers
1,234
12,121
3,434
123

このように、sedの置換コマンドは、区切り文字の使い分け、「&」によるマッチ文字列の再利用、そしてグルーピングと後方参照を組み合わせることで、非常に強力なテキスト処理ツールへと進化します。日々のシェルスクリプト作業やログ整形の際に、ぜひこれらのテクニックを活用してみてください。

  1. ShellCheckとは?シェルスクリプトのバグや問題点を検出できる静的解析ツールの使い方

    ShellCheckは、bash/shシェルスクリプトに含まれる問題のあるコードに対して、警告や改善提案を表示してくれる静的解析ツールです。利用方法は複数あります。たとえば https://www.shellcheck.net にアクセスし、オンラインエディタ(Ace – JavaScript製のスタンドアローンコードエディタ)にスクリプトを貼り付ければ、即座にフィードバックを得られます。このサイトは常に最新のgitコミットに同期されており、ShellCheckを手軽に試せる最も簡単な方法です。 また、自身のマシンにインストールしてターミナルから実行したり、テキストエディタやビルド・テストスイ

  2. Vimで新規シェルスクリプトに自動でカスタムヘッダーを挿入するテンプレート設定方法

    この記事では、Vimエディタで新しく作成するすべてのbashスクリプトに、カスタムヘッダーを自動的に挿入するための簡単な設定方法を紹介します。この設定を行うことで、vi/vimエディタで新しい .sh ファイルを開くたびに、カスタムヘッダーが自動的にファイルの先頭へ追加されるようになります。 bashスクリプト用カスタムヘッダーテンプレートファイルの作成方法 まずは、カスタムbashスクリプトヘッダーの内容を記述したテンプレートファイル sh_header.temp を作成します。ホームディレクトリ配下の ~/.vim/ ディレクトリなどに保存しておくと管理しやすいでしょう。 $ vi ~/.