MacOSのsedの動きがわからない


数値キー項目をDWHから抽出したのはいいけど、DBには文字列型で格納されているから、'(シングルクォート)で囲んで、レコードごとにカンマで区切りたい
そういうこと、よくありますよね。

Unix系OSのターミナル(もしくはWSL環境)にはsedというコマンドがあります。
ストリームエディタと呼ばれるエディタで、文字列の置換などを得意としています。

詳しいことは他の記事に譲るとして。

今回の用件は、

  • 数値キー項目が1行ワンレコードとしてファイルに格納されている
keys
111111
22222
3333
444
55555
....
  • 各レコードの項目を'(シングルクォート)で囲みたい
  • 各レコードの末尾に,(カンマ)を入れたい

というものでした。
つまりこうなるはずです。

result
'111111',
'22222',
'3333',
'444',
'55555',
....

sedを使えばちょー簡単ですね。


$ sed -e "s/\([0-9]\+\)/'\1',/g"  keys > result

結果を確認

$ cat result
111111
22222
3333
444
55555
....

なんでや?!
正規表現のグルーピングの括弧のエスケープを外してみる

$ sed -e "s/([0-9]\+)/'\1',/g" keys > result
sed: 1: "s/([0-9]\+)/'\1'/g
": \1 not defined in the RE

ようわからんけど怒られた・・・
-Eを-eにすればいい、みたいな記事もあったぞ(逆だけど)

$ sed -E "s/([0-9]\+)/'\1',/g" keys > result
$ cat result
111111
22222
3333
444
55555
....

だめだこりゃ
いっそ、正規表現の+の前のエスケープも消したろ

$ sed -E "s/([0-9]+)/'\1',/g" keys > result
$ cat result
'111111',
'22222',
'3333',
'444',
'55555',
....

でけた!
・・・わからん。manコマンドで確認してみよう。

$ man sed
SED(1)                    BSD General Commands Manual                   SED(1)

NAME
     sed -- stream editor

SYNOPSIS
     sed [-Ealn] command [file ...]
     sed [-Ealn] [-e command] [-f command_file] [-i extension] [file ...]
(中略)
     -E      Interpret regular expressions as extended (modern) regular
             expressions rather than basic regular expressions (BRE's).  The
             re_format(7) manual page fully describes both formats.

-E を使えば拡張(現代的な)正規表現がつかえるぞ、と。後方参照機能は拡張正規表現に含まれるぞな、もし、と。

Linuxのsedは,,+などを\(バックスラッシュ)でエスケープする必要があるのですが、MacOSの場合はいらないようです。

おまけ

面倒臭いのでコマンドを"(ダブルクォート)で囲ってましたが、これを'(シングルクォート)のままにする場合はどうなるのか

$ sed -E 's/([0-9]+)/'"'"'\1'"'"',/g' keys > result
$ cat result
'111111',
'22222',
'3333',
'444',
'55555',
....
  1. 'でリテラルを閉じます
  2. "で前側の'を囲みます。("'")
  3. 'で後方参照(\1)を囲みます('\1')
  4. "で後ろ側の'を囲みます。("'"
  5. 'で後ろ側の'より後ろのリテラルを始めます

意外と苦労しました・・・