アプリ版:「スタンプのみでお礼する」機能のリリースについて

正規表現について教えてください。
JavaScriptでプログラミングを行っています。
その中で文字列に対しゼロサプレスを行いたいと思い
調べた結果、正規表現を使用する以下のコードで
実現可能なことが分かりました。

val.replace(/^0+([0-9]+.*)/, "$1")

コードを記述し実行すると確かに可能なのですが
正規表現を調べてみても何故これでゼロサプレスが可能なのか
よく理解できませんでした。
申し訳ありませんが初心者でも理解できるように説明して頂けないでしょうか。
宜しくお願いします。

A 回答 (5件)

正規表現のプロではないですが、自分なりに分解して説明してみます。



^   …文字列の先頭から
0+   …「0に一致」と「直前の文字の1回以上に一致」、あわせて「1文字以上の'0'の連続」
(   …グループ化の始まり マッチした部分が$1に格納される
[0-9]+ …「'0'から'9'に一致」と「直前の文字の1回以上に一致」、あわせて「1文字以上の'0'から'9'の連続」
.*   …「任意の一文字(\n以外)」と「直前の文字の0回以上に一致」、あわせて「任意の文字列」
)   …グループ化の終わり

まとめると
文字列の先頭から1文字以上の'0'の連続があり、それ以降の'0'から'9'の連続と、残りの文字列が、$1に格納される
と解釈できます。

そしてマッチした部分(今回の場合は文字列全体)が、$1に置き換えられます。

マッチしなかった場合(今回の場合1文字目が0じゃない場合)は、置換が実行されず元の文字列のままになります。
    • good
    • 0

#4です。


すみません、間違いがありました。

#3さんのおまけにありますが、
00などの時に、0を残さないといけないのですね・・・。失念していました。

なので、最後の2行は無視してください。
    • good
    • 0

まずお手元に適当な資料を用意。


http://www.tohoho-web.com/js/string.htm#replace
http://www.tohoho-web.com/js/regexp.htm

順番に見てみると、

1. 「^0+」は「文字列先頭で1個以上の0とマッチ」
2. 「[0-9]+.*」は「1個以上の数値と以降の任意文字列」

と言えるかと思います。
Javascriptの場合、デフォルトで最大マッチなので、1の方で先頭から続く0を全てマッチさせることができます。

正規表現に含まれる括弧は、くくった順に$1, $2,...で参照できるようになります。
よってreplaceでは、第二引数で$1を指定することにより、正規表現全体にマッチした部分を、2の部分だけに置き換える、という処理が行われます。

なお、2に関しては、そんなに詳細に指定しなくても、別に「.*」でも良い気がします。
もっと言えば、replaceですので「val.replace(/^0+/, "")」のように、なくても良いと思います。
    • good
    • 0

正規表現は苦手なので詳しいわけではないのですが、つたない説明を…


(だからって、他のものが得意ってわけでもないけど)

まず、正規表現の概要やメタ文字の意味などについては、以下など参照してください。
(ぐぐれば解説はたくさん見つかると思います)
 http://www.site-cooler.com/kwl/javascript/15.htm
 http://www.albert2005.co.jp/study/javascript/reg …


> /^0+([0-9]+.*)/
を分解して大雑把に説明すると
 ^0+ = 行頭が0で始まる一文字以上の連続する0
 [0-9]+ = 一文字以上の連続する数字(=0~9まで)
 .* = 0個(=なし)以上の文字列
 () = グループを指定 (この部分が$1として参照される)
という意味になります。
要は{ 「前ゼロ部分」(「連続する数字」+「文字列」) }という部分が見つかったら、()内(=$1)に置き換える(=reolace)ということになります。(「文字列」はなくてもよい)

例として"0000123"を考えた場合、マッチすることはわかると思いますが、0 と 000123 などのように分割されてもよさそうに思えます。
しかし、正規表現の場合、+や*の指定では、なるべく長い文字列をヒットさせるというルールになっているようで、この場合先にある「^0+」に対してできるだけ長くとると「0000」が該当するように解釈されて、0000 と 123 という分割になり、"0000123"→"123"という置き換え結果になります。

"0000123.456"や"0000123E45"のような場合は、数字の後ろに小数点やEが出てきたら、最後の.*に該当しますが、この部分は「数字以外の文字が出た後の文字全部」と言い換えることができますので、結局()ブロックには前ゼロ部分以外の残り全部がマッチすることになります。
(このルールを変える表現として +? や *? などがありますが、調べてみてください)
^0+となっているので、"$0000123"みたいに先頭に記号があったり、" 0000123"のように空白があるだけでもマッチしなくなります。 

おまけ
"00"の場合は、[0-9]+に対して1個以上の0がマッチの条件となるので0 と 0に分けられて、結果、0に置き換えられることになります。
"0"の場合には、^0+と[0-9]+でそれぞれ1個以上の0(または数字)がなければならないので、マッチしないことになり置き換えはおきません。(結果は"0"のまま)


多分、事前に数値であることのチェックを別途行っていると思いますが、文字列の"ID007"や"007:ID"を対象に考えてみるとそれぞれ
 "ID007" → ID007 (マッチしない)
 "007:ID" → 7:ID (マッチして置き換わる)
のようになります。


などと調べていたら、↓にちょっと面白い記事がありましたので、ご参考まで。
 http://d.hatena.ne.jp/koseki2/20090530/JsIdiom
    • good
    • 0

この正規表現の説明だけ聞いても、ふふーん となるだけで、


たいして知識にならないでしょう。参考サイトをいくつか挙げるので、
ちゃんと、自分で調べてみましょう!

http://www.site-cooler.com/kwl/javascript/15.htm
http://www.kt.rim.or.jp/~kbk/regex/regex.html
http://www.komonet.ne.jp/~perl/chap7.htm
http://www.mnet.ne.jp/~nakama/

とはいえ、お礼が欲しいから、つたない解説(うまく説明できてないかも...

val.replace(/^0+([0-9]+.*)/, "$1")
はvalの中で^0+([0-9]+.*)というパターンにマッチしたものを
([0-9]+.*)に置き換えます。 ※([0-9]+.*)が$1になります。

^0+([0-9]+.*)は「行の先頭に0が1文字以上有り、続いて0から9の文字の
どれかが1文字以上有り、続いて任意の文字が0文字以上ある」というパターン
です。
()内グループサブマッチのパターン [0-9]+.* の意味は、「0から9の文字の
どれかが1文字以上有り、続いて任意の文字が0文字以上ある」というパターン
です。 ※先の0は0+で取得されてるからこのグループには入らない
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!