热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
本提示词专为Java开发场景设计,能够根据具体任务需求生成精准、高效的正则表达式解决方案。提示词采用结构化工作流程,从需求分析到代码实现层层递进,确保生成的正则表达式既符合Java语法规范又满足实际业务需求。特别适用于文本处理、数据验证、模式匹配等开发场景,提供技术解释和最佳实践建议,帮助开发者理解实现原理并应用于实际项目。
需求分析
正则表达式
设计思路:
组成片段(Java 字符串常量形式):
完整模式(带命名捕获组,大小写不敏感,通过 Pattern.CASE_INSENSITIVE 设置):
最终组合(展示为 Java 中的字符串):
捕获组说明:
Java代码实现
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NginxClientIpExtractor {
// 八位组 0-255
private static final String OCTET = "(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)";
// 通用 IPv4
private static final String IPV4 = OCTET + "(?:\\." + OCTET + "){3}";
// 需跳过的私有/回环/链路本地网段
private static final String PRIVATE_IP =
"(?:"
+ "10\\." + OCTET + "\\." + OCTET + "\\." + OCTET
+ "|192\\.168\\." + OCTET + "\\." + OCTET
+ "|172\\.(?:1[6-9]|2\\d|3[0-1])\\." + OCTET + "\\." + OCTET
+ "|127\\." + OCTET + "\\." + OCTET + "\\." + OCTET
+ "|169\\.254\\." + OCTET + "\\." + OCTET
+ ")";
// 公网 IPv4(用前缀否定前瞻排除上述网段)
private static final String PUBLIC_IPV4 =
"(?!(?:10|127)\\.|192\\.168\\.|169\\.254\\.|172\\.(?:1[6-9]|2\\d|3[0-1])\\.)" + IPV4;
// 完整提取模式:
// 1) XFF: 跳过若干私网IP + 捕获首个公网IP 到命名组 xff
// 2) 行首: 捕获公网IP 到命名组 remote
private static final String REGEX =
"(?:\\bX-Forwarded-For\\s*:\\s*(?:\\s*(?:" + PRIVATE_IP + ")\\s*,)*\\s*(?<xff>" + PUBLIC_IPV4 + ")\\b)"
+ "|(?:^\\s*(?<remote>" + PUBLIC_IPV4 + ")\\b)";
// 编译 Pattern(大小写不敏感即可匹配 X-Forwarded-For 大小写变体)
private static final Pattern PATTERN = Pattern.compile(REGEX, Pattern.CASE_INSENSITIVE);
/**
* 从单行 Nginx 访问日志中提取真实客户端公网 IPv4。
* 优先 X-Forwarded-For 中首个公网 IP;否则回退到行首公网 IP;都没有则返回 Optional.empty()。
*/
public static Optional<String> extractClientIp(String logLine) {
if (logLine == null || logLine.isEmpty()) {
return Optional.empty();
}
Matcher m = PATTERN.matcher(logLine);
if (!m.find()) {
return Optional.empty();
}
String ip = m.group("xff");
if (ip == null) {
ip = m.group("remote");
}
return Optional.ofNullable(ip);
}
// 示例演示
public static void main(String[] args) {
String l1 = "198.51.100.23 - - [2025-06-01T12:41:22+08:00] \"GET /api\" 200";
String l2 = "203.0.113.5 - - [2025-06-01] \"GET /\" 200 \"X-Forwarded-For: 10.0.0.2, 203.0.113.5\"";
System.out.println(extractClientIp(l1).orElse("<none>")); // 198.51.100.23
System.out.println(extractClientIp(l2).orElse("<none>")); // 203.0.113.5
}
}
使用说明
测试示例 使用 JUnit 5 的单元测试,覆盖边界与典型场景。
import org.junit.jupiter.api.Test;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
public class NginxClientIpExtractorTest {
@Test
void test_NoXff_UseRemoteAddr_Public() {
String line = "198.51.100.23 - - [2025-06-01T12:41:22+08:00] \"GET /api\" 200";
assertEquals(Optional.of("198.51.100.23"), NginxClientIpExtractor.extractClientIp(line));
}
@Test
void test_Xff_FirstPublicChosen() {
String line = "203.0.113.5 - - [2025-06-01] \"GET /\" 200 \"X-Forwarded-For: 10.0.0.2, 203.0.113.5\"";
assertEquals(Optional.of("203.0.113.5"), NginxClientIpExtractor.extractClientIp(line));
}
@Test
void test_Xff_AllPrivate_FallbackToRemotePublic() {
String line = "203.0.113.9 - - [2025-06-01] \"GET /\" 200 \"X-Forwarded-For: 10.0.0.1, 172.31.2.3, 192.168.1.9\"";
assertEquals(Optional.of("203.0.113.9"), NginxClientIpExtractor.extractClientIp(line));
}
@Test
void test_NoXff_RemoteIsPrivate_NoResult() {
String line = "10.1.2.3 - - [2025-06-01] \"GET /\" 200";
assertTrue(NginxClientIpExtractor.extractClientIp(line).isEmpty());
}
@Test
void test_Xff_SkipLoopback_ThenPublic() {
String line = "10.0.0.9 - - [2025-06-01] \"GET /\" 200 \"X-Forwarded-For: 127.0.0.1, 198.51.100.77\"";
assertEquals(Optional.of("198.51.100.77"), NginxClientIpExtractor.extractClientIp(line));
}
@Test
void test_Xff_SpacesAndMixed() {
String line = "203.0.113.10 - - [2025-06-01] \"GET /\" 200 \"X-Forwarded-For: 10.0.0.1 , 203.0.113.88 , 192.168.1.1\"";
assertEquals(Optional.of("203.0.113.88"), NginxClientIpExtractor.extractClientIp(line));
}
@Test
void test_172_15_IsPublic_NotExcluded() {
String line = "172.15.1.2 - - [2025-06-01] \"GET /\" 200";
assertEquals(Optional.of("172.15.1.2"), NginxClientIpExtractor.extractClientIp(line));
}
@Test
void test_169_254_Excluded() {
String line = "169.254.1.2 - - [2025-06-01] \"GET /\" 200";
assertTrue(NginxClientIpExtractor.extractClientIp(line).isEmpty());
}
@Test
void test_MalformedOrEmptyLine() {
assertTrue(NginxClientIpExtractor.extractClientIp("").isEmpty());
assertTrue(NginxClientIpExtractor.extractClientIp(null).isEmpty());
}
}
预期结果(部分):
最佳实践
需求分析
正则表达式
^ORD-(?<date>[0-9]{8})-(?<tail>(?=(?:.*[A-Z]){2,})[A-Z0-9]{6})$
Java代码实现
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class OrderIdValidator {
// 编译后的正则,建议长期复用,避免重复编译带来的开销
private static final Pattern ORDER_ID_PATTERN = Pattern.compile(
"^ORD-(?<date>[0-9]{8})-(?<tail>(?=(?:.*[A-Z]){2,})[A-Z0-9]{6})$"
);
// 严格日期解析器:用于“业务层面”的真实日期合法性校验(非正则内完成)
private static final DateTimeFormatter DATE_FMT_STRICT =
DateTimeFormatter.ofPattern("uuuuMMdd").withResolverStyle(ResolverStyle.STRICT);
private OrderIdValidator() {}
// 仅做格式校验(正则),不验证日期真伪
public static boolean isFormatValid(String orderId) {
if (orderId == null) return false;
return ORDER_ID_PATTERN.matcher(orderId).matches();
}
// 同时做格式校验与真实日期校验(严格)
public static boolean isStrictValid(String orderId) {
Optional<OrderParts> partsOpt = parse(orderId);
if (!partsOpt.isPresent()) return false;
return isRealDate(partsOpt.get().getDate());
}
// 分组提取(成功则返回日期与尾段);仅在格式匹配时返回
public static Optional<OrderParts> parse(String orderId) {
if (orderId == null) return Optional.empty();
Matcher m = ORDER_ID_PATTERN.matcher(orderId);
if (!m.matches()) return Optional.empty();
String date = m.group("date");
String tail = m.group("tail");
return Optional.of(new OrderParts(orderId, date, tail));
}
// 业务层面:严格日期校验(yyyyMMdd必须为真实日期)
public static boolean isRealDate(String yyyyMMdd) {
try {
LocalDate.parse(yyyyMMdd, DATE_FMT_STRICT);
return true;
} catch (Exception e) {
return false;
}
}
// 示例:批量校验并打印结果
public static void main(String[] args) {
List<String> samples = new ArrayList<>();
// 题中样例(格式应匹配)
samples.add("ORD-20251206-AB12X9");
samples.add("ORD-20241130-1A2B3C");
samples.add("ORD-20240230-ABC123"); // 非真实日期
// 边界/对照样例
samples.add("ORD-20251206-A12345"); // 尾段仅1个字母 -> 格式应失败
samples.add("ORD-20251206-123456"); // 尾段0个字母 -> 格式应失败
samples.add("ORD-20251206-AB12x9"); // 含小写x -> 格式应失败
samples.add("ORD-20251206-AB12X9X"); // 尾段长度7 -> 格式应失败
samples.add("ORD-2025120-AB12X9"); // 日期7位 -> 格式应失败
samples.add("ORD-20251306-AB12X9"); // 13月(格式匹配,但真实日期失败)
samples.add("XXX-20251206-AB12X9"); // 前缀错误 -> 格式应失败
samples.add("ORD-abcdefgh-ABC123"); // 日期非数字 -> 格式应失败
samples.add("ORD-20251206-AB12X@"); // 非法字符@ -> 格式应失败
samples.add("ORD-20251206-AAAAAA"); // 6字母 -> 格式应通过,真实日期也通过
for (String s : samples) {
boolean formatOk = isFormatValid(s);
Optional<OrderParts> parts = parse(s);
boolean realDateOk = parts.map(p -> isRealDate(p.getDate())).orElse(false);
System.out.printf(
"%-25s | format=%-5s | date=%-8s | tail=%-6s | realDate=%-5s%n",
s,
formatOk,
parts.map(OrderParts::getDate).orElse("-"),
parts.map(OrderParts::getTail).orElse("-"),
realDateOk
);
}
}
// 简单数据承载类
public static final class OrderParts {
private final String original;
private final String date; // yyyyMMdd
private final String tail; // 6位大写字母/数字(至少2个字母)
public OrderParts(String original, String date, String tail) {
this.original = original;
this.date = date;
this.tail = tail;
}
public String getOriginal() { return original; }
public String getDate() { return date; }
public String getTail() { return tail; }
@Override public String toString() {
return "OrderParts{date=" + date + ", tail=" + tail + "}";
}
}
}
使用说明
测试示例(期望结论)
最佳实践
 与反引号包裹的代码片段(包括行内 ... 与围栏 ...)。http|https|ftp 三类 URL。\])。.../a(b)c,需避免在第一个 ) 处提早结束。![...] 与普通链接 [...] 的区分。为保证可维护性与性能,采用“两阶段策略”:
主匹配(提取普通超链接,忽略图片):
(?<!!)\[((?:\\.|[^\[\]\n])+?)\]\(\s*((?:https?|ftp)://[^\s)]+(?:\([^ \s)]*\)[^\s)]*)*)\s*(?:\s+(?:"[^"]*"|'[^']*'|\([^)]*\)))?\s*\)
(?<!!):负向前瞻,确保 [ 前一字符不是 !(排除图片 )。\[((?:\\.|[^\[\]\n])+?)\]:捕获链接文本(第1组)。
(?:\\.|[^\[\]\n])+? 允许转义字符(如 \])与除 [] 和换行外的任意字符,惰性匹配。\( 与 \):包裹 URL(及可选 title)。\s*((?:https?|ftp)://[^\s)]+(?:\([^ \s)]*\)[^\s)]*)*)\s*:捕获 URL(第2组)。
http|https|ftp。[^ \s)]+(?:\([^ \s)]*\)[^\s)]*)* 允许 URL 中出现成对的圆括号,不被外层 ) 提前截断。(?:\s+(?:"[^"]*"|'[^']*'|\([^)]*\)))?:可选的 title(不计入 URL 捕获)。\s*\):关闭链接的 )。代码片段屏蔽(两类):
``` ... ```(跨行)
`[^`]*`import java.util.*;
import java.util.regex.*;
/**
* 从 Markdown 文本中提取普通超链接 (text, url),忽略图片和反引号代码片段。
*/
public class MarkdownLinkExtractor {
// 1) 屏蔽代码片段的正则
private static final Pattern CODE_FENCE = Pattern.compile("(?s)```.*?```"); // 跨行围栏代码块
private static final Pattern CODE_INLINE = Pattern.compile("`[^`]*`"); // 行内代码
// 2) 提取普通链接的正则(两组:1=text, 2=url)
private static final String LINK_REGEX =
"(?<!!)\\[((?:\\\\.|[^\\[\\]\\n])+?)\\]\\(\\s*((?:https?|ftp)://[^\\s)]+(?:\\([^\\s)]*\\)[^\\s)]*)*)\\s*(?:\\s+(?:\"[^\"]*\"|'[^']*'|\\([^)]*\\)))?\\s*\\)";
private static final Pattern LINK_PATTERN = Pattern.compile(LINK_REGEX);
// 3) 反转义链接文本中的常见转义(如 \], \[, \(, \), \\)
private static final Pattern LINK_TEXT_ESCAPES = Pattern.compile("\\\\([\\\\\\[\\]\\(\\)])");
public static class Link {
public final String text;
public final String url;
public Link(String text, String url) { this.text = text; this.url = url; }
@Override public String toString() { return "(" + text + ", " + url + ")"; }
}
/**
* 提取 Markdown 普通链接 (text, url),忽略图片与反引号代码。
*/
public static List<Link> extractMarkdownLinks(String markdown) {
if (markdown == null || markdown.isEmpty()) return Collections.emptyList();
// 第一步:屏蔽代码片段(替换为空格,保持长度不变,避免打乱后续匹配的索引)
String masked = maskBySpaces(markdown, CODE_FENCE);
masked = maskBySpaces(masked, CODE_INLINE);
// 第二步:在屏蔽后的文本中查找普通链接
List<Link> result = new ArrayList<>();
Matcher m = LINK_PATTERN.matcher(masked);
while (m.find()) {
String rawText = m.group(1);
String url = m.group(2);
// 反转义链接文本中的常见转义序列
String text = unescapeLinkText(rawText);
result.add(new Link(text, url));
}
return result;
}
// 用空格覆盖匹配到的区间(不改变字符串长度)
private static String maskBySpaces(String input, Pattern p) {
Matcher m = p.matcher(input);
StringBuilder sb = new StringBuilder(input);
while (m.find()) {
for (int i = m.start(); i < m.end(); i++) {
sb.setCharAt(i, ' ');
}
}
return sb.toString();
}
// 将 \[, \], \(, \), \\ 反转义为本体
private static String unescapeLinkText(String s) {
return LINK_TEXT_ESCAPES.matcher(s).replaceAll("$1");
}
// Demo
public static void main(String[] args) {
String md = ""
+ "这是正文 [接口文档](https://docs.example.org/v1/api) 与 [下载](ftp://files.example.org/a.zip)。\n"
+ " `代码含 [假链](http://x)`\n";
List<Link> links = extractMarkdownLinks(md);
for (Link link : links) {
System.out.println(link);
}
}
}
(text, url) 列表。... 与围栏代码 ...http|https|ftp 链接输入(包含题目给定用例):
代码里的 [假链](https://no.example) 与 真链。```js
// [假链](https://no.example)
外面有 真链
[^\\s)]+(?:\\([^\\s)]*\\)[^\\s)]*)*,在大多数实际 URL 中表现稳定。打造一套“即插即用”的智能提示词,让AI以资深Java正则专家的身份,快速把零散需求转化为可直接落地的方案:从需求拆解到模式设计,再到可复制的Java示例、测试用例与优化建议,一次性生成。通过标准化输出与清晰解释,帮助个人与团队在文本处理、数据校验、日志解析、数据提取等高频场景中,显著降低试错成本、提升交付速度与代码质量,并沉淀可复用的工程化资产,最终实现更高的效率与更稳定的产出。
快速产出注册登录、订单号、邮件手机号等校验规则;一键生成可运行示例与测试用例,直接接入服务;减少边界漏判与性能问题,缩短上线周期。
为接口与日志断言生成稳定的匹配表达式;批量构造边界用例,自动校正误报漏报;将回归校验固化为可复用模板。
从网页与文本中提取价格、时间、地址等关键信息;一键适配多地区格式差异;借助示例代码快速嵌入到数据清洗流程。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
半价获取高级提示词-优惠即将到期