質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

2120閲覧

文字列の最後に「都道府県」が設定されているか正規表現で正しく確認できない。

kamekameusagi

総合スコア1

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2021/05/04 02:13

実現したいこと

Nodeで都道府県名を扱うプログラムを作成しています。
配列に保存されている都道府県名の末尾に「都道府県」が設定されていることを正規表現で確認したいと考えていますが、正常に動作しません。

発生している問題

大阪府を除いたデータは正常に判断されますが、「大阪府」がfalseと判定されます。

東京都 is true 東京 is false 神奈川県 is true 神奈川 is false 北海道 is true 大阪府 is false 大阪 is false

該当のソースコード

javascript

1const prefs = ['東京都', '東京', '神奈川県', '神奈川', '北海道', '大阪府', '大阪']; 2const reg = /[都道府県]$/g; 3 4prefs.forEach(pref => { 5 if (reg.test(pref)) { 6 console.log(pref + ' is true'); 7 } else { 8 console.log(pref + ' is false'); 9 } 10});

試したこと

gオプションを外すと正常に動作します。
gオプションをつけたままで、配列prefsの大阪府の前の北海道を削除すると正常に動作します。
ちなみに、regex101.comで正規表現を/[都道府県]$/mgとし、以下のテストデータを入力すると、大阪府も正常に(具体的には大阪府の「府」が)マッチしました。
TEST EXPRESSION
東京都
東京
神奈川県
神奈川
北海道
大阪府
大阪

補足情報(FW/ツールのバージョンなど)

Nodeのバージョンはv14.16.1です。

正規表現の考え方が間違っている、または、日本語の問題なのか、ご存じの方、アドバイス&ヒントをお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

gを付けないと、正規表現は対象文字列の先頭から検索を開始します。
gを付けると、前回のマッチの次、具体的にはlastIndexプロパティの位置から検索を開始します。
検索後にconsole.log(reg.lastIndex);を入れてみましょう。

"北海道"検索では2文字目にマッチしたので、lastIndexは3になり、次の"大阪府"は3文字目つまり"府"の次から検索を開始して見つからないという結果になります。

"北海道"を取ると、直前の検索は"神奈川"ですがこれにはマッチしないのでlastIndexは0になり、次の"大阪府"は先頭から検索を開始して見つかるという結果になります。

testメソッドであればgを付けないというのが正解だと思いますが、他の目的とregを共用するので付けたいと言うことであれば、マッチの前にreg.lastIndex = 0;を入れれば良いと思います。

投稿2021/05/04 02:48

otn

総合スコア84538

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamekameusagi

2021/05/04 03:55

ありがとうございます。MDNをよく読むとgフラグは内部状態を持つことが記載されていました。配列の要素を1つずつ処理するため、その度に文字列の先頭から処理されると「思い込んで」しまいました。gフラグをつけない方式を採用させていただきます。
guest

0

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#using_test_on_a_regex_with_the_global_flag
globalフラグが付いているので、前回の'北海道'でのtest結果のlastIndex(3)の影響で、大阪府は空文字扱いになります。

それはそうと、京都がtrueになるのはOKなんですかね、、?

投稿2021/05/04 02:46

matukeso

総合スコア1590

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/05/04 03:55

逆に、「東京都府中市」を「東京都府」という都道府県だと誤認するバグを起こしたこともあります。
kamekameusagi

2021/05/04 04:00

MDNに分かりやすく、はっきりを書いていますね。内部状態を持つ関数の怖さを思い知りました…
guest

0

node 14.15.4 で試した所、
test()から match()に代えたら正しく判定されました。

javascript

1pref.match(reg);

大阪府を先頭に東京都の前にもってきたら,大阪府はtrue, 東京都が false になりました。
なんでしょうねえ

投稿2021/05/04 02:43

hide5stm

総合スコア426

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

const reg = new RegExp('[都道府県]$');ではどうでしょう?
TypeScript: Typed JavaScript at Any Scale.ではこれでうまくいきました。

投稿2021/05/04 02:36

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

itagagaki

2021/05/04 02:39

根本原因はわかりませんが、回避策ということで。
itagagaki

2021/05/04 02:51

RegExp('[都道府県]$', 'g') だと結局ダメですね…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問