前回、質問内容に漏れがあり再現することができませんでした。
https://teratail.com/questions/239924
行いたい正規表現は以下の通りで試行錯誤しているのですが、うまくいかないので教えていただきたいです。
文字列 | 期待値 |
---|---|
漢字 |
OK |
カタカナ |
OK |
漢字カタカナ |
OK |
あ漢字カタカナ |
NG |
漢字あカタカナ |
NG |
漢字カタカナあ |
NG |
半角スペース | 期待値 |
---|---|
漢字カタカナ |
NG |
漢字カタカナ |
NG |
漢字 カタカナ |
OK |
漢字 カタカナ |
NG |
漢字 カ タカナ |
OK |
漢字 カ タカナ |
NG |
漢字カタカナ |
NG |
漢字カタカナ |
NG |
全角スペース | 期待値 |
---|---|
漢字カタカナ |
NG |
漢字カタカナ |
NG |
漢字 カタカナ |
OK |
漢字 カタカナ |
NG |
漢字 カ タカナ |
OK |
漢字 カ タカナ |
NG |
漢字カタカナ |
NG |
漢字カタカナ |
NG |
基本的な許容文字形式に加え、文字列の間にあるスペースは1つまでとしたいのです。
追記
細かいところは以下のように定めたいと思います。
要件
漢字とカタカナの入力を許容し、
全角ハイフン(長音)と全角スペースと半角スペースも許容するが
全角ハイフン(長音)と全角スペースと半角スペースについては連続で1文字までしか入力できないものとする。
漢字の取り扱い
- ここでいう漢字とは、全角で1文字を表すものとする。
- ㍻などのような環境依存文字は漢字と見做さない。
- 吉野家などのような
吉
のような文字列でも人間が見て全角で1文字を表す漢字だと判断できるものは漢字と見做す。
カタカナの取り扱い
- ここでいうカタカナとは、全角で1文字を表すものとし、以下のみをカタカナとして取り扱う。
清音
アイウエオ
カキクケコ
サシスセソ
タチツテト
ナニヌネノ
ハヒフヘホ
マミムメモ
ヤユヨ
ラリルレロ
ワヰヱヲ
ン
濁音
ガギグゲゴ
ザジズゼゾ
ダヂヅデド
バビブベボ
ヴ
半濁音
パピプペポ
その他
ヴ
ァィゥェォ
ヵヶッ
ャュョ
ヮ
以下は漢字で変換できるためカタカナとは認めない。(漢字とするかカタカナとするか悩ましい)
ヵヶ
スペースの取り扱い
- 文頭の全角及び半角スペースは許容しない。
- 文末の全角及び半角スペースは許容しない。
- 文中の全角及び半角スペースは2文字連続に限り許容しないが、1文字でづつであれば文中何度出現しても許容する。
※以下に例を示すが、全角スペースも同様の扱いとする。
テスト文字列 | 期待値 |
---|---|
漢字 カタカナ |
OK |
漢字 カタカナ |
NG |
漢字 カ タカナ |
OK |
漢字 カ タカナ |
NG |
漢 字 カ タ カ ナ |
OK |
漢 字 カ タ カ ナ |
NG |
全角ハイフン(長音)の取り扱い
- 文中の全角ハイフン(長音)は2文字連続に限り許容しないが、1文字でづつであれば文中何度出現しても許容する。
- 全角ハイフン(長音)はカタカナとして表現できる文中にしか存在してはならず、カタカナの文頭には含んではならないが文末には含むことができる。
- 長音はひらがなかカタカナまでは区別する必要はなく、人間が全角ハイフンだとわかれば良い(ここは、あえて曖昧さを残す)
テスト文字列 | 期待値 |
---|---|
漢ー字ギータ |
NG |
漢字ギータ |
OK |
漢字ギーター |
OK |
漢字ギーーター |
NG |
漢字ギター |
OK |
漢字ーギター |
NG |
漢字ギータ |
OK |
ギーター漢ー字 |
NG |
ギーター漢字 |
OK |
ギーーター漢字 |
NG |
ギター漢字 |
OK |
ーギター漢字 |
NG |
検証方法
カスタムルールとしてグローバルに使いまわしたいため、以下の形式のコードでtest関数を用いてチェックするものとする。
const pattern = /^([ァ-ン一-龥][ ]?)*(((([ァ-ン]|ー)[ ]?)*([ァ-ン]|ー))|[一-龥])$/
console.log(pattern.test(value))
---
正規表現でここまで苦戦するとは思ってなかったので、連続スペースとかハイフンかと、もうサーバー側で修正した方が早いかも。
フロント側でもきっちりやりたいのは単なる自己満なので。。。
なんだか手を出しちゃいけないものにハマっていってる気がする。
最終追記
既存の一致項目に影響がないまま、項33~43までの期待値と結果が一致することで良しとしたいと思います。
https://codepen.io/postman_tyo/pen/vYOOLNL
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
+5
漏れがあったのは要件が正確ではなく、曖昧な部分があるからです。厳格な要件を定めるところから始めなければなりません。
要件
- HTML5の
input
要素におけるpattern
属性に使用し、入力値のチェックに使用する。 - 対応ブラウザはPC環境のみターゲットとし、最新のGoogle Chrome、Chromium版Microsoft Edge、Apple Saffariとする。その他のブラウザは考慮しない。
- 漢字とカタカナのみで構成される場合のみマッチする。
- 漢字はScriptプロパティが
Han
であるUnicode文字とする。 Han
には、JIS未登録の日本では使用されない漢字も含まれる。Han
には、㍻
(U+337B)のような漢字を使用したCJK互換用文字は含まれない。- カタカナはScriptプロパティが
Katakana
であるUnicode文字とー
長音記号(U+30FC)とする。 Katakana
には、ㇰ
(U+31F0)等の片仮名拡張やア
(U+FF71)等の半角・全角形の半角片仮名、㌀
(U+3300)等の片仮名のみで構成されたCJK互換用文字が含まれる。(他にもあるかも知れない)Katakana
には、片仮名体系にある゠
、・
、ー
と言った記号や、゛
、゜
と言った濁点・半濁点は含まれない。- 例外として、漢字またはカタカナの間に
- スペースと和字間隔は、両方が連続してあってはならない。
- スペースと和字間隔は、連続して二つ以上あってはならない。
- スペースと和字間隔は、漢字と漢字、カタカナとカタカナ、漢字とカタカナおよびその逆の間であっても良い。
- 合字や結合文字は考慮せず、コードポイント単位で判断する。
ヴ
(U+30F4)はカタカナとするがヴ
(U+30A6 U+3099)はカタカナとはしない。 - UTF-16ではサロゲートペアになってしまう文字であっても、一つのコードポイントとして判定する。
- 空文字列は
pattern
でのチェックが行われないが、マッチはさせない。 - 対応するUnicodeのバージョンはブラウザの実装に依存とする。
- 正規表現はASCII文字のみを使用して表現する。
正規表現
(\p{Script=Han}|\p{Script=Katakana}|\u30FC)+([ \u3000](\p{Script=Han}|\p{Script=Katakana}|\u30FC)+)*
Google Chrome 80.0.3987.87 でのみ確認しています。その他のブラウザでは確認していませんが、Chromium版Microsoft Edge、Apple Saffariでも動作すると思われます。
確認用HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>確認用</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script type="module">
const form = document.getElementById('form');
const inputText = document.getElementById('inputText');
inputText.addEventListener('input', () => {
if (inputText.value) {
form.classList.add('was-validated');
} else {
form.classList.remove('was-validated');
}
});
</script>
</head>
<body>
<div class="container-fluid mt-2 mx-2">
<form id="form">
<div class="form-group row">
<label for="inputText" class="col-sm-2 col-form-label">テキスト入力</label>
<div class="col-sm-8">
<input id="inputText" class="form-control" type="text" pattern="(\p{Script=Han}|\p{Script=Katakana}|\u30FC)+([ \u3000](\p{Script=Han}|\p{Script=Katakana}|\u30FC)+)*">
<div class="valid-feedback">
OK
</div>
<div class="invalid-feedback">
NG
</div>
<div>
</div>
</form>
</div>
</body>
</html>
私が書いた要件と期待しているものが異なるというのであれば、上に書いた要件のように厳格な要件を質問に追記してください。
-
回答の評価を上げる
以下のような回答は評価を上げましょう
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
こんにちは
以下でどうでしょう?
const regexp = /^([一-龥][ ]?)*(((([ァ-ン]|ー)[ ]?)*([ァ-ン]|ー))|[一-龥])$/
上記の正規表現で、ご質問にある各文字列をテストするコードを作成して、以下に上げておきました。
以下で、試すことができると思います。
- git clone https://github.com/jun68ykt/q240432.git
- cd q240432
- yarn install
- yarn test
以下は、上記の手順を私の手元のターミナルで行ったときのキャプチャです。
以上、参考になれば幸いです。
投稿
score 6661
-
回答の評価を上げる
以下のような回答は評価を上げましょう
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 89.65%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼