51307

[code]

    Regex.Replace("HogeFugaPiyoHogera", "([a-z])([A-Z])", "$1-$2")
    
[/code]

上記の置換を行うと、結果は

[code]

    Hoge-Fuga-Piyo-Hogera
    
[/code]

となります。

場合によっては有用な置換方法だと思いますが、  
どのような原理でこのような結果になるのか理解できません。

わかりやすく説明して頂けないでしょうか？


CC BY-SA 4.0
2018-12-16T12:55:53.243
51262
2018-12-17T16:48:55.967
3925
question
c# 正規表現
正規表現を使った置換


ここでキーとなるのは`()`と`$1`です。  
正規表現の中で`()`でくくられた部分をグループ化することができます。  
そして、`$1`は１番目にマッチしたグループを指します。  
同じように、`$2`は２番目にマッチしたグループを指します。  
`()`の数が3つなら`$3`まで、`()`の数が4つなら`$4`までと、いくらでも増やすことができます。

これらを使うことによって、部分置換をできるようになります。

例えば以下のように部分置換をするとします。

> この文字列を...  
>  090-1234-5678 1234  
>  このように変換したい  
>  090-1234-5678 内線1234

その場合、以下のようなコードで部分置換ができます。

[code]

    Regex.Replace("090-1234-5678 1234", "(\\d{4}$)", "内線$1");
    //結果: 090-1234-5678 内線1234
    
    //説明:
    //090-1234-5678 1234という文字列から、下４桁の数字の部分のみを探し、その部分をグループ１と解釈する。
    //グループ１の前に「内線」という文字を追加する。
    
[/code]

正規表現からカッコをとった場合はどうなるでしょうか？

[code]

    Regex.Replace("090-1234-5678 1234", "\\d{4}$", "内線$1");
    //結果: 090-1234-5678 内線$1
    
    //説明: 
    //カッコがないので、グループ化された部分はないとみなされる。
    //グループがないので$1は「ひとつめのグループを指すもの」ではなく、「$1」という文字列扱いになるため、
    //下４桁は「内線$1」として置換される
    
[/code]

ご質問の例の場合：

[code]

    Regex.Replace("HogeFugaPiyoHogera", "([a-z])([A-Z])", "$1-$2")
    //結果: Hoge-Fuga-Piyo-Hogera
    
    //説明: 
    //大文字の前にある小文字の部分をグループ１とする($1)
    //小文字の次の続く大文字の部分をグループ２とする($2)
    //$1と$2の間に線をいれる
    
[/code]


CC BY-SA 4.0
2018-12-16T21:18:33.710
51270
2018-12-16T21:37:37.880
2018-12-16T21:37:37.880
31397
31397
51262
answer


### 正規表現パターン `([a-z])([A-Z])`

`[]` は中に記述されたいずれかの１文字に一致することを示すパターンです。  
ここでの特殊な書き方として `a-z` として記述することで a から z までの文字を意味します。  
つまり `[a-z]` は `[abcdefghijklmnopqrstuvwxyz]` と同じです。  
なので `[a-z]` は「アルファベット小文字１文字」を示します。

同様に `[A-Z]` は「アルファベット大文字１文字」を示します。

`[a-z][A-Z]` で「アルファベット小文字のあとにアルファベット大文字」のパターンを示します。

入力文字列でこのパターンに当てはまるのが `eF` `aP` `oH` の３箇所です  
入力文字列上では "Hog **eF** ug **aP** iy **oH** ogera" の太字の部分です。

`()`はグループ化する指定で、一致したパターンの文字列を記憶します。  
`([a-z])([A-Z])`
は、「`[a-z]`でマッチした文字」をグループ１、「`[A-Z]`でマッチした文字」をグループ２として記憶します。グループ番号は`()`で指定した順番で決まります。  
記憶した文字列は置換先で使用されます。

* * *

### 置換文字列 `$1-$2`

マッチした部分を指定した文字列に置き換えます。この文字列は正規表現ではありません。  
ここでのマイナス文字は前述の `a-z` のような特殊な意味はなく、そのまま `-` という文字です。  
`$1` `$2` はパターンマッチで記憶されたしたグループ１、グループ２の文字列に対応します。

これを適用すると、 `eF` `aP` `oH` は `e-F` `a-P` `o-H` に置換されます。

結果、入力文字列は "Hog **e-F** ug **a-P** iy **o-H** ogera"
という文字列に変換されます。太字の部分が置換された部分です。


CC BY-SA 4.0
2018-12-17T16:41:34.713
51307
2018-12-17T16:48:55.967
2018-12-17T16:48:55.967
14817
14817
51262
answer