Skip to content

Commit

Permalink
正規表現辞書機能の改善
Browse files Browse the repository at this point in the history
  • Loading branch information
shiro8613 committed Jan 31, 2024
1 parent 7080a10 commit 239f39b
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.jetbrains.annotations.Unmodifiable;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
Expand All @@ -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) {
Expand Down
177 changes: 83 additions & 94 deletions core/src/main/java/dev/felnull/itts/core/dict/RegexUtil.java
Original file line number Diff line number Diff line change
@@ -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<RegexOption> optionList = new ArrayList<>();

/** 日本語と英語をわけます */
private List<String> splitJapaneseEnglish(String text) {
String[] dividedText = text.split("");
List<String> 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<Pattern, String> 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<String, Boolean> testFunction) {
this.optionList.add(new RegexOption(priority, replacedText, testFunction));
return this;
}

/**
Expand All @@ -79,47 +65,50 @@ public RegexUtil() {
* @return 置き換え済みテキスト
*/
public String replaceText(String text) {

//空の文字列用配列
List<String> 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<String> texts = splitJapaneseEnglish(text);
List<String> 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<Entry<Pattern, String>> entrySet = dictMap.entrySet();

//ループを回して、当てはまるモノが一個でもあったら終了
for (Entry<Pattern, String> 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<String, Boolean> testFunction;

/** 置き換えテキスト*/
public String replacedText;

/**
* コンストラクタ
*
* @param priority 優先度
* @param replacedText 置き換えテキスト
* @param testFunction 置き換え判定用関数
*/
public RegexOption(int priority, String replacedText, Function<String, Boolean> testFunction) {
this.priority = priority;
this.replacedText = replacedText;
this.testFunction = testFunction;
}
}
}

/*
使い方
RegexUtil rgUtil = new RegexUtil();
String out = rgUtil.replaceText(ここにURLとかが含まれたテキスト);
*/
}

0 comments on commit 239f39b

Please sign in to comment.