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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

3回答

3682閲覧

Go言語の正規表現がうまくできない

dvamp

総合スコア39

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2022/02/12 04:29

編集2022/02/14 09:21

Go言語でパスワードの正規表現を書こうとしています。
実現したい内容は半角英字、数字、記号(ASCIIで!から〜まで)をそれぞれ1種類以上を含む6文字以上かどうかをチェックする正規表現です。
Go言語では肯定先読みをサポートしていないため他言語のような正規表現ができません。
また、https://teratail.com/questions/377534 の質問を参考に単一の正規表現を使うのではなく、段階的にチェックする方法にしようとしています。
しかし、!から~の正規表現を!-~でプログラムに渡すと、記号を使っていない文字列でも含まれているという結果になり、うまくいきません。

Go

1package main 2 3import ( 4 "regexp" 5 "testing" 6) 7 8func MatchPassword(password string) bool { 9 if len(password) < 6 { // 6文字以上か判定 10 return false 11 } 12 reg := []*regexp.Regexp{ 13 regexp.MustCompile(`[A-Za-z]`), 14 regexp.MustCompile(`\d`), 15 regexp.MustCompile(`[!-~]`), 16 } 17 for _, r := range reg { 18 if r.FindString(password) == "" { 19 return false 20 } 21 } 22 return true 23} 24 25func TestMatchPassword(t *testing.T) { 26 cases := []struct { 27 input string 28 want bool 29 }{ 30 {"1aZ", false}, // 6文字未満だからだめ 31 {"zJmsZJiKeS", false}, // 数字と記号がないからだめ 32 {"v0x51aip1t", false}, // 記号がないのにtrueが帰ってきているので、[!-~]の正規表現が正しくないことまではわかります 33 } 34 35 for i, p := range cases { 36 got := MatchPassword(p.input) 37 if got != p.want { 38 t.Errorf("unexpected ExcelColumn result, case=%d, input=%s, got=%v, want=%v", 39 i+1, p.input, got, p.want) 40 } 41 } 42}

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

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

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

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

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

guest

回答3

0

ベストアンサー

同じようなことで困っていて先日解決できたので共有します。
https://pkg.go.dev/regexp/syntax を見るとわかりますが、

[!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])

なので期待通りの動作になりません。
また、書かれたコードでは [あいうえお] などの半角英数字記号以外でもOKとなるので、期待しているものには足りません。
期待している動作になるコードだと以下になるかと思います。

Go

1package main 2 3import ( 4 "regexp" 5 "testing" 6) 7 8func MatchPassword(password string) bool { 9 if len(password) < 6 { // 6文字以上か判定 10 return false 11 } 12 if !(regexp.MustCompile("^[0-9a-zA-Z!-/:-@[-`{-~]+$").Match([]byte(password))) { // 英数字記号以外を使っているか判定 13 return false 14 } 15 reg := []*regexp.Regexp{ 16 regexp.MustCompile([[:alpha:]]), // 英字が含まれるか判定 17 regexp.MustCompile([[:digit:]]), // 数字が含まれるか判定 18 regexp.MustCompile([[:punct:]]), // 記号が含まれるか判定 19 } 20 for _, r := range reg { 21 if r.FindString(password) == "" { 22 return false 23 } 24 } 25 return true 26} 27 28func TestMatchPassword(t *testing.T) { 29 cases := []struct { 30 input string 31 want bool 32 }{ 33 {"1aZ", false}, // 6文字未満だからだめ 34 {"zJmsZJiKeS", false}, // 数字と記号がないからだめ 35 {"v0x51aip1t", false}, // 記号がないからだめ 36 {"Ab1あ!?", false}, // 英数字記号以外があるからだめ 37 {"Ab12!?", true}, // 英数字記号のみすべて含まれているのでOK 38 } 39 40 for i, p := range cases { 41 got := MatchPassword(p.input) 42 if got != p.want { 43 t.Errorf("unexpected result, case=%d, input=%s, got=%v, want=%v", 44 i+1, p.input, got, p.want) 45 } 46 } 47}

投稿2022/02/14 07:51

編集2022/02/14 09:20
changeworld

総合スコア60

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

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

dvamp

2022/02/14 09:30

回答ありがとうございました。 仰る通り、他の方からの回答いただいたものに変えると半角英字、数字、記号以外を使われても通ってしまうものでしたので、ベストアンサーとさせていただきます。
melian

2022/02/14 11:21

その正規表現ですと、例えば、 "Ab 12!?" というパスワード文字列(スペースが含まれます)の場合、false になってしまいます。なので、スペースやタブを許容するのであれば、 regexp.MustCompile("^[\t[:print:]]+$").Match([]byte(password)) とする方が良さそうです。
guest

0

[!-~]は、「半角ASCII文字全部(空白除く)」なので、英字数字も含みますよ。
英数字を除くのなら、[!-/:-@{-~]でしょうか。

投稿2022/02/12 05:04

otn

総合スコア86295

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

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

dvamp

2022/02/14 09:33

ご回答ありがとうございました!
guest

0

!0x21~0x7E になります。そのため、正規表現 [!-~] は数字と大文字・小文字のアルファベット(0-9, a-z, A-Z)全てを含むことになります。なので、以下の様に記号部分だけを指定します。ただ、バッククォートを含みますので、正規表現をダブルクォート(")で囲んでいます。

go

1 //regexp.MustCompile(`[!-~]`), 2 regexp.MustCompile("[!-/:-@[-`{-~]"),

追記

ドキュメントを眺めますと、文字クラス [[:punct:]] を使うことができる様です。

Go言語: パッケージ syntax

ASCII 文字クラス:

[[:punct:]] 句読点 (== [!-/:-@[-`{-~])

go

1 //regexp.MustCompile(`[!-~]`), 2 regexp.MustCompile(`[[:punct:]]`),

投稿2022/02/12 05:03

編集2022/02/12 05:46
melian

総合スコア21118

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

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

dvamp

2022/02/14 09:33

ご回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問