※ Visual Studio Code の話題です
結論を先に
数字とひっついてようが気にせず$10
で置換しちゃいましょう。
いい感じに置換してくれます。
なお、ご想像の通り限界があります。(後述)
やりたいこと
以下のようなテキストファイルがあったとします。
(PowerShellでls -r > out.txt
した結果の一部で、実際には数千行くらいあります)
ディレクトリ: F:\Nintendo\Album
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/02/04 3:30 2020
d----- 2020/12/31 0:55 2019
d----- 2021/01/01 17:39 2021
d----- 2022/01/13 9:02 2022
d----- 2023/02/19 13:18 2023
時刻表示のケタが揃っていなくて扱いづらいです。
置換して00:00
の表記にしましょう。
どうやるの
とりあえず簡単にこうしてみました。
^(d----- +20../../.. +) (\d:\d\d)
↓
$10$2
…これだとグループの番号が10
だと認識されそうですね。
が、気にせず置換してみちゃいます。
ディレクトリ: F:\Nintendo\Album
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2020/02/04 03:30 2020
d----- 2020/12/31 00:55 2019
d----- 2021/01/01 17:39 2021
d----- 2022/01/13 09:02 2022
d----- 2023/02/19 13:18 2023
ちゃんといい感じに00:00
の表記に置換できました。
グループ10
が存在しない場合、いい感じにグループ番号と文字0
を分割してくれるようです。
わーぱちぱちー。
めでたしめでたし。
ちょっと待って
今回は偶然グループ10
が無かったから上手に置換できたけど…
グループ10
があった場合どうすれば…?
試しに、無理やりこんな感じの正規表現にしてみました。
^(d----- +20../../.. +) (\d:\d\d)(( )( )( )( )( )( )( ))
↓
$10$2$3
(
...)
のグルーピングが合計で10個あります。
これはあくまでも例なので変なことをしていますが、グループが10以上になるのは十分あり得る話でしょう。
(タブ区切りのCSVで([^\t]+)\t([^\t]+)\t ... \t([^\t]+)
とやったりとか…)
ひとまずさっきのファイルで置換してみます。
ディレクトリ: F:\Nintendo\Album
Mode LastWriteTime Length Name
---- ------------- ------ ----
3:30 2020
0:55 2019
d----- 2021/01/01 17:39 2021
9:02 2022
d----- 2023/02/19 13:18 2023
予想通り、$10
がグループ10
だと認識され、ただの空白に置換されてしまいました。
グループ番号と数字を分割する方法は無いんでしょうか?
調べた範囲では方法はありませんでした…
なんとか置換する方法
${1}0
的な感じに分割することはできないし、名前付きキャプチャもできないみたいだしなので、一時文字列を経由して置換を2回行うしか方法は無さそうです。
$1(@@@@@ファイル中に存在しない文字列#####)0
みたいな文字列にいったん変換したあと、
(@@@@@ファイル中に存在しない文字列#####)
↓
(空文字列)
というように置換することでなんとか…
一般的なプログラミング言語では…
※ 注:知ってる限りです
PHP (PCRE)
PHP(PCRE)では、${1}0
と表記することでグループと数字を分割できます。
(?P<name>pattern)
とすることで名前付きキャプチャも可能ですが、置換先の指定では参照できないようです。
サクラエディタ(確認済)など、Onigumoを使う正規表現なら似たような結果になると思われます。
参考:PHP: preg_replace - Manual
参考:PHP: サブパターン - Manual
実行結果:https://wandbox.org/permlink/D4mvwFMVrvYj4WvK
Python
Pythonでは、\g<1>1
と表記することでグループと数字を分割できます。
また、(?P<name>pattern)
⇒\g<name>
とすることで名前付きキャプチャを用いた置換も可能です。
参考:re --- 正規表現操作 — Python 3.11.2 ドキュメント
実行結果:https://wandbox.org/permlink/N9FCFQwquJfVYf2E
JavaScript
JavaScriptでは、グループ番号と数字は分割できないようです。
その代わり、(?<name>pattern)
⇒$<name>
とすることで名前付きキャプチャを用いた置換が可能です。
…VSCodeはChromiumなのでJSでの正規表現に対応してくれてても良いと思うのですが…。
参考:グループと後方参照 - JavaScript | MDN
参考:String.prototype.replace() - JavaScript | MDN
実行結果:https://wandbox.org/permlink/vO9418qsSl41GXdx
なお、古いブラウザでは未対応のようです。
ブラウザによってはそこそこ最近の実装みたい。
⇒ JavaScript built-in: RegExp: Named capture groups | Can I use... Support tables for HTML5, CSS3, etc
⇒ RegExp - JavaScript | MDN(Named capture groups の行)
参考ページ等