こういう文字列を
aaa,bbb,0 aaa,bbb,,1 aaa,bbb,2
このように置換したいと思いました。
aaa,bbb,,0 aaa,bbb,,1 aaa,bbb,,2
で、こういう正規表現を書いたのです。
s/(?<!,)(?=,.)$/,/g
この正規表現を先頭から説明すると、
- 前の文字がカンマでない
- 続く文字がカンマ、そして更に任意の一文字
- その後はすぐに行末
である「位置」にマッチし(戻り読み、先読みは文字列ではなく「位置」にマッチする)、
そこにカンマを挿入するという意図で書きました。
しかしこれが動かないという。
うーむ何故だ?
と暫く考えていたのですが、気づきました。行末記号が悪さをしていたということに。
先程の正規表現をよーく見てみると、
(?<!,)(?=,.)$
- 前の文字がカンマでない
- 続く文字がカンマ、そして更に任意の一文字
- その後はすぐに行末
ではなく、
- 前の文字がカンマでない
- 続く文字がカンマ、そして更に任意の一文字
である位置、かつ
- すぐに行末
であるという文字列にマッチせよという意味になります。
つまり、文字列の途中なのに行末という、ありえないマッチを指定していたわけです。
正解
この場合、
(?<!,)(?=,.$)
と書けばOK。これで本来意図した意味になります。