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

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

ただいまの
回答率

91.77%

  • Java

    9652questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • 正規表現

    524questions

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

正規表現で日本語を取得したい

解決済

回答 4

投稿 2017/09/13 22:38

  • 評価
  • クリップ 1
  • VIEW 116

Matt

score 17

教えてもらいたいこと

任意の文字列から,日本語の部分をString配列orListで取得する方法が知りたいです.

日本語取得の例

下のコードであれば,出力結果は「亜 え ふ ぃ えふ ふぃ えふぃ」(順不同)となってほしいです.

public static void main(String[] args) {
    String str = "g亜nergえふぃwjtoo";

    String regex = "「日本語を取得する正規表現」";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher("aaaaa");

    while(m.find()) {
        System.out.print(m.group() + "");
    }
}

今分かっていること

・日本語(ひらがな,カタカナ,漢字)を表す正規表現:[亜-熙ぁ-んァ-ヶ](調べると色々あるみたいなので,これが正確というものがあれば教えて頂きたいです)
・最小マッチ,最大マッチの方法

よろしくお願いします.

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

Unicodeの文字のブロックに触れてみる

// 平仮名4つ
System.out.println( "ひらがな".matches( "\\p{InHiragana}{4}" ) );
    // => true

// カタカナ4つ
System.out.println( "カタカナ".matches( "\\p{InKatakana}{4}" ) );
    // => true

// 漢字2つ
System.out.println( "漢字".matches( "\\p{InCjkUnifiedIdeographs}{2}" ) );
    // => true


漢字は日本のものに限定できないようですが

必要に応じて以下等も追加してください

  • CJK_SYMBOLS_AND_PUNCTUATION
  • CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A

投稿 2017/09/13 23:03

編集 2017/09/13 23:30

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2017/09/13 23:14

    Unicode試してみました.正規表現は[亜-熙ぁ-んァ-ヶ]より,上記の方がよいのでしょうか?

    キャンセル

  • 2017/09/13 23:27 編集

    [亜-熙]はShift-JISでのコードポイントが前提なのでダメなようです。
    Unicodeの場合に日本の常用漢字を範囲で表すと[一-龠]になるようです。

    JavaScriptで漢字を表す正規表現 http://stabucky.com/wp/archives/7594

    キャンセル

  • 2017/09/13 23:44

    どれが適切か、というのは結局どこまでマッチさせたいか、もしくはマッチしてしまっても許容するかという要件次第です

    Unicodeで「漢字」の正規表現 http://tama-san.com/kanji-regex/

    キャンセル

  • 2017/09/14 00:22

    [一-龠]を使うことにします

    キャンセル

checkベストアンサー

+1

Javaの正規表現マッチングでは、一度読み込んだ文字を巻き戻してもう一度読み込むということはできない(後読みというのはあるが、位置に関するマッチングを行うだけで巻き戻してマッチさせるということができない)ので、マッチングのみでご質問の結果を得ることはできません。
いったん日本語部分の文字列をすべて取り出した後、各文字列から部分文字列をすべて取り出すという作業を別途行う必要があります。

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.stream.Stream.Builder;

public class Q92346 {

    public static void main(String[] args) {
        String str = "g亜nergえふぃwjtoo";

        String regex = "[一-龠ぁ-ゞァ-ヶ]+";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str);
        Builder<String> builder = Stream.builder();

        while(m.find()) {
            builder.accept(m.group());
        }

        builder.build()
            .flatMap(Q92346::partials)
            .forEachOrdered(System.out::println);

    }

    public static Stream<String> partials(String target) {
        Builder<String> builder = Stream.builder();
        for (int i = 0; i < target.length(); i++) {
            for (int j = i + 1; j <= target.length(); j++) {
                builder.accept(target.substring(i, j));
            }
        }
        return builder.build();
    }

}

投稿 2017/09/14 01:51

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2017/09/18 13:55

    正規表現は戻ることができないのですね.べんきょうになりました.

    キャンセル

+1

javaは知らないので、正規表現のみ示します。

/\p{Katakana}+/
/\p{Hiragana}+/
/\p{Han}+/
/\p{Katakana}+?/
/\p{Hiragana}+?/
/\p{Han}+?/


上から、
1文字以上のカタカナ(最大マッチ)
1文字以上のひらがな(最大マッチ)
1文字以上の漢字(最大マッチ)
1文字以上のカタカナ(最小マッチ)
1文字以上のひらがな(最小マッチ)
1文字以上の漢字(最小マッチ)

投稿 2017/09/13 22:49

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2017/09/13 23:01

    \p{Katakana}などの正規表現は使えないようです.

    キャンセル

+1

まずはご質問事項に回答致します。

日本語(ひらがな,カタカナ,漢字)を表す正規表現:[亜-熙ぁ-んァ-ヶ](調べると色々あるみたいなので,これが正確というものがあれば教えて頂きたいです)

私は2バイト文字を探す、という意味で "[^\x01-\x7E]" をよく使用しています。個人的にはこれがおすすめですが色んな方法があると思いますので色々調べてみると面白いと思います。

最小マッチ,最大マッチの方法

上記正規表現にて最小マッチと最大マッチを実行する場合、
最大マッチは

[^\x01-\x7E]+


最小マッチは

[^\x01-\x7E]+?

となります。
+はその前のセンテンス(今回の場合は「[^\x01-\x7E]+」)が1文字以上であること、という意味です。
また、?を付与することで最小マッチという意味になります。

さて、コードについてですが、最小マッチと最大マッチを同時に取得する正規表現は簡単には実施できませんし、そのような正規表現が書けたとしても一般的な理解しやすい正規表現ではなくなると予想できますので、おすすめできません。自分以外のコーダーがそのソースを見てもすぐに理解できないからです。

そこで、以下のように一度最大マッチで文字列を取得した後、Javaプログラムにてマッチした文字列の成形を実施するパターンはいかがでしょうか。

    public static void main(String[] args) {

        // 検索対象文字列
        String str = "g亜nergえふぃwjtoo";

        // 正規表現パターン(最長マッチ)
        String regex = "[^\\x01-\\x7E]+";

        // 正規表現オブジェクト取得
        Pattern p = Pattern.compile(regex);

        // パターンマッチ実施
        Matcher m = p.matcher(str);

        // 全マッチを走査
        while (m.find()) {

            // マッチ結果をバッファ取得
            String buf = m.group();

            // マッチした文字列を文字数ごとに分割して出力
            for (int i = 1; i <= buf.length(); i++) {
                for (int j = 0; j <= buf.length() - i; j++) {
                    System.out.print(buf.substring(j, j + i) + " ");
                }
            }

        }
    }

投稿 2017/09/17 01:07

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

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

ただいまの回答率

91.77%

関連した質問

  • 解決済

    androidのxmlPullParserを使ったパース処理

    XmlPullParserを使ってXMLのパース処理をしています。 下記のようなdescriptionタグのsrc=の画像URL抜き出したいのですが、簡単に抜き出すことはできない

  • 解決済

    Javaで正規表現でテキストを抜き出したい

    Java初心者です 正規表現で質問です。 eの文字列から、 attribute ref="ap: と " で囲まれた文字列部分(つまりlやr) を抜き出したいと考

  • 解決済

    C# 正規表現

    PDFの見積書にて、 [文字列1]が「代価-」+半角数字1~2桁を含んでいたら。その「代価-数字」を[文字列2]にする。 というif文を作りたいのですが、これを正規表現

  • 解決済

    正規表現 マッチした文字列の取得

    Javaの正規表現とMatcherクラスを組み合わせた使い方が理解できず、教えていただけないでしょうか? ・やりたいこと 以下のようなhtml文のうち 2016年11

  • 解決済

    AndroidアプリのJavaの正規表現でHTMLソースから住所を抜き出したい

    前提・実現したいこと 今目的のページのURLからHTMLソースを取得し、そこからそのページに書かれている住所の取得をしたく奮闘しているところです。 目的のページは各自治体の避難

  • 解決済

    Javaのテキストを日付に変換したい

    Javaで西暦、年号がバラバラのデータ(格納されている日付データの型はString型)の フォーマットを整形したい場合の書き方を教えて頂きたいです。 例)2015年7月26日メ

  • 解決済

    文字列の語尾が数字の部分を正規表現で取得したい

    Javaにて文字列の語尾が数字の部分を正規表現で取得したいと思っておりますがどうすればよろしいでしょうか。何卒ご教授お願いいたします。 例) 取得前:おはようございます1

  • 解決済

    文字列中で、AをBに、BをAに置換したい。

    質問 表題の通り、任意の文字列中の、アルファベットAをBに、BをAに置換したいです。 Stringクラスの、replaceAllメソッドを使えば、AをBに置換することはできます

同じタグがついた質問を見る

  • Java

    9652questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • 正規表現

    524questions

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