From 239f39b8f7517125b4c7daf2b4278a96144f9859 Mon Sep 17 00:00:00 2001 From: toms0910 Date: Thu, 1 Feb 2024 00:37:41 +0900 Subject: [PATCH] =?UTF-8?q?=E6=AD=A3=E8=A6=8F=E8=A1=A8=E7=8F=BE=E8=BE=9E?= =?UTF-8?q?=E6=9B=B8=E6=A9=9F=E8=83=BD=E3=81=AE=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/dict/AbbreviationDictionary.java | 35 +++- .../dev/felnull/itts/core/dict/RegexUtil.java | 177 ++++++++---------- 2 files changed, 117 insertions(+), 95 deletions(-) diff --git a/core/src/main/java/dev/felnull/itts/core/dict/AbbreviationDictionary.java b/core/src/main/java/dev/felnull/itts/core/dict/AbbreviationDictionary.java index ecbf286..d722c27 100644 --- a/core/src/main/java/dev/felnull/itts/core/dict/AbbreviationDictionary.java +++ b/core/src/main/java/dev/felnull/itts/core/dict/AbbreviationDictionary.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.Unmodifiable; import java.util.Map; +import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -22,7 +23,39 @@ public class AbbreviationDictionary implements Dictionary { /** * 正規表現関係 */ - private final RegexUtil regexUtil = new RegexUtil(); + private final RegexUtil regexUtil = new RegexUtil() + .addOption(1, "ユーアルエルショウリャク", s -> { + Pattern pattern = Pattern.compile("https?://[\\w!?/+\\-_~=;.,*&@#$%()'\\[\\]]+"); + Matcher matcher = pattern.matcher(s); + return matcher.find(); + }) + .addOption(1, "ドメインショウリャク", s -> { + Pattern pattern = Pattern.compile("^([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\\.)+[a-zA-Z]{2,}$"); + Matcher matcher = pattern.matcher(s); + return matcher.find(); + }) + .addOption(1, "アイピーブイフォーショウリャク", s -> { + Pattern pattern = Pattern.compile("(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"); + Matcher matcher = pattern.matcher(s); + return matcher.find(); + }) + .addOption(1, "アイピーブイロクショウリャク", s -> { + Pattern pattern = Pattern.compile("(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|" + + "([0-9a-fA-F]{1,4}:){1,7}:|" + + "([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" + + "([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" + + "([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|" + + "([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" + + "([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|" + + "[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" + + ":((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]+|" + + "::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\\.){3}(25[0-5]|" + + "(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|" + + "(2[0-4]|1?[0-9])?[0-9])\\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))"); + Matcher matcher = pattern.matcher(s); + return matcher.find(); + }); + @Override public @NotNull String apply(@NotNull String text, long guildId) { diff --git a/core/src/main/java/dev/felnull/itts/core/dict/RegexUtil.java b/core/src/main/java/dev/felnull/itts/core/dict/RegexUtil.java index a517f15..19ca098 100644 --- a/core/src/main/java/dev/felnull/itts/core/dict/RegexUtil.java +++ b/core/src/main/java/dev/felnull/itts/core/dict/RegexUtil.java @@ -1,75 +1,61 @@ package dev.felnull.itts.core.dict; import java.util.*; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.function.Function; /** * 正規表現関係 * - * @author toms0910 + * @author shiro8613 */ public class RegexUtil { - // ここから下、パターン群 - - /** - * URLの正規表現 - */ - private static final Pattern URL_REGEX = Pattern.compile("^(https?|ftp|file|s?ftp|ssh)://([\\w-]+\\.)+[\\w-]+(/[\\w\\- ./?%&=~#:,]*)?"); - - /** - * ドメインの正規表現 - */ - private static final Pattern DOMAIN_REGEX = Pattern.compile("^([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\\.)+[a-zA-Z]{2,}$"); - - /** - * IPv4の正規表現 - */ - private static final Pattern IPV4_REGEX = Pattern.compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"); - - /** - * IPv6の正規表現 - */ - private static final Pattern IPV6_REGEX = Pattern.compile("((([0-9A-Fa-f]{1,4}:){1,6}:)|(([0-9A-Fa-f]{1,4}:){7}))([0-9A-Fa-f]{1,4})$"); - - // ここから下、置き換えテキスト群 - - /** - * URLの置き換えテキスト - */ - private static final String URL_REPLACE_TEXT = "ユーアールエルショウリャク"; - - /** - * ドメインの置き換えテキスト - */ - private static final String DOMAIN_REPLACE_TEXT = "ドメインショウリャク"; - - /** - * IPv4の置き換えテキスト - */ - private static final String IPV4_REPLACE_TEXT = "アイピーブイフォーショウリャク"; + /** オプション保持用のリスト */ + private final List optionList = new ArrayList<>(); + + /** 日本語と英語をわけます */ + private List splitJapaneseEnglish(String text) { + String[] dividedText = text.split(""); + List createdText = new ArrayList<>(); + StringBuilder tmpText = new StringBuilder(); + boolean en = false; + + for (String txt :dividedText) { + if (txt.matches("[A-Za-z0-9:/#$%&.,-?_]+")) { + if (!en) { + createdText.add(tmpText.toString()); + tmpText.setLength(0); + } + en = true; + tmpText.append(txt); + } else { + if (en) { + createdText.add(tmpText.toString()); + tmpText.setLength(0); + en = false; + } + tmpText.append(txt); + } + } - /** - * IPv6の置き換えテキスト - */ - private static final String IPV6_REPLACE_TEXT = "アイピーブイロクショウリャク"; + if (!tmpText.isEmpty()) { + createdText.add(tmpText.toString()); + } - /** - * パターンと置き換えテキストのマップ - */ - private final Map dictMap = new HashMap<>(); + return createdText; + } /** - * コンストラクタ + * オプション追加 + * + * @param priority 優先度 + * @param replacedText 置き換えテキスト + * @param testFunction 置き換え判定用関数 + * @return this このクラスが返ってきます */ - public RegexUtil() { - //マップに登録 - dictMap.put(URL_REGEX, URL_REPLACE_TEXT); - dictMap.put(DOMAIN_REGEX, DOMAIN_REPLACE_TEXT); - dictMap.put(IPV4_REGEX, IPV4_REPLACE_TEXT); - dictMap.put(IPV6_REGEX, IPV6_REPLACE_TEXT); + public RegexUtil addOption(int priority, String replacedText, Function testFunction) { + this.optionList.add(new RegexOption(priority, replacedText, testFunction)); + return this; } /** @@ -79,47 +65,50 @@ public RegexUtil() { * @return 置き換え済みテキスト */ public String replaceText(String text) { - - //空の文字列用配列 - List returnText = new ArrayList<>(); - - //改行コードを空白に変換 - String replaceNewLine2SpaceText = text.replace("\n", " "); - //空白ごとに分割 - String[] dividedSpaceTexts = replaceNewLine2SpaceText.split(" "); - - //分割されたテキストを一区切りごとに処理を実行 - for (String dividedSpaceText : dividedSpaceTexts) { - //replacerで一致したテキストを置き換える - String replacedText = replacer(dividedSpaceText); - //書き出し用の配列に入れる - returnText.add(replacedText); + List texts = splitJapaneseEnglish(text); + List createdText = new ArrayList<>(); + + LOOP: for (String txt :texts) { + for (RegexOption ops :optionList.stream().sorted(Comparator.comparingInt(o -> o.priority)).toList()) { + if (ops.testFunction.apply(txt)) { + createdText.add(ops.replacedText); + continue LOOP; + } + } + createdText.add(txt); } - //配列を一つのテキスト(空白つき)に連結してかえす - return String.join(" ", returnText); + return String.join(" ", createdText); } - private String replacer(String text) { - //MapをEntrySetに変換 - Set> entrySet = dictMap.entrySet(); - - //ループを回して、当てはまるモノが一個でもあったら終了 - for (Entry entries : entrySet) { - //マップから取得したパターンとテキストの比較 - Matcher matcher = entries.getKey().matcher(text); - if (matcher.find()) { //テキスト内に一致したら - //置き換え済みテキストをかえす - return matcher.replaceAll(entries.getValue()); - } - } - return text; + /** オプション定義用クラス + * + * @author shiro8613 + * */ + public static class RegexOption { + + /** プライオリティ */ + public int priority; + + /** 判定関数 */ + public Function testFunction; + + /** 置き換えテキスト*/ + public String replacedText; + + /** + * コンストラクタ + * + * @param priority 優先度 + * @param replacedText 置き換えテキスト + * @param testFunction 置き換え判定用関数 + */ + public RegexOption(int priority, String replacedText, Function testFunction) { + this.priority = priority; + this.replacedText = replacedText; + this.testFunction = testFunction; + } } -} -/* - 使い方 - RegexUtil rgUtil = new RegexUtil(); - String out = rgUtil.replaceText(ここにURLとかが含まれたテキスト); -*/ +} \ No newline at end of file