是否可以使用“$1”作为另一个方法的参数并将返回的字符串放在它在 .replaceAll 中的位置上?
Is it possible to use "$1" as argument for another method and place returned String on it's place in .replaceAll?
我正在编写标签->HTML 解析器 - 用户输入一些带有自定义标签的文本(介于 BB 和 Markdown 之间的东西,例如 [b]
或 [#RRGGBB]
),然后它正在解析到 HTML - 因此 [#FF0000]red text[/#]
变成 <span style='color:#FF0000;'>red text</strong>
,然后以 HTML 样式放置在 JTextPane 中。
所有用户标签和 HTML 存储在 HashMap 中并像这样解析:
public static String parseBBToHTML(String text) {
String html = text;
Map<String,String> bbMap = new HashMap<String , String>();
bbMap.put("\[b\]", "<strong>");
bbMap.put("\[/b\]", "</strong>");
...
bbMap.put("\[color=(.+?)\]", "<span style='color:;'>");
bbMap.put("\[/color\]", "</span>");
for (Map.Entry entry: bbMap.entrySet()) {
html = html.replaceAll(entry.getKey().toString(), entry.getValue().toString());
}
return html;
}
然后返回值用于 JTextPane 中的 .setText() 以及其他方法的动画效果,只需一个接一个地键入字母并在它们之间暂停。
一切正常,但现在我在想一件事:
我在用空 HTML 标签模仿打字动画时的暂停,如下所示:<!!!!!!!!!!>
所以 10 个“!”它们之间有 20 毫秒的停顿,给我 200 毫秒的停顿。
我正在用这个方法形成 "pause tags"(它的参数是 int,但你会明白,为什么我现在使用 String):
public static String pause(String ms){
String pausedText = "";
int time = Integer.parseInt(ms);
for (int i = 0; i < (time/animationSpeed); i++) {
pausedText = pausedText + "!";
}
return "<"+pausedText+">";
}
我想使用像 [!2000]
这样的标签来暂停 2000 毫秒。所以我只是像这样输入我的解析器字符串:
bbMap.put("\[\!(.+?)\]", Dialogue.pause(""));
...它没有用。它在方法 Dialogue.pause literally 字符串“$1”中给出,而不是 </code> 作为解析值。</p>
<p>如何使用 <code>
作为参数来形成 "pause tag" 并将其放在文本中?
在Java中$1在捕获命令之外没有特殊意义,不是全局变量。您需要解析字符串并将组捕获到局部变量中以便将来使用它。
看这里:Java Regex Replace with Capturing Group
这意味着您当前使用 bbMap 的方法不适用于这些替换。
您可以这样做:运行 首先修改您的 bbMap。然后运行第二组修改bbMap2,首先捕获组,计算长度,根据长度创建你想要的字符串,然后替换。
如果我没有记错,用你的其他代码调用 bbMap.put("\[\!(.+?)\]", Dialogue.pause(""));
你想实现这样的事情:
- 正则表达式找到组 1 的匹配项
- Dialogue.pause("$1") 使用第 1 组的内容(应该是一个数字)调用
问题是它不能那样工作,因此您可以考虑重构您的代码。与其遍历可能的标签(即 bbMap
中的条目)并在输入中查找它们,不如遍历输入,获取开始和结束标签并在地图中进行查找。
你可以用正则表达式做到这一点,但请注意,这与 HTML 有同样的问题:它不适合正则表达式,除非你真的知道数据的结构等等。
所以您可能想要做的是使用表达式查找所有标签,获取标签 name/content 然后进行替换。它可能看起来像这样:
Pattern tagPattern = Pattern.compile("\[(/?)([^\]]*)\]");
Matcher tagMatcher = tagPattern.matcher( input );
StringBuffer output = new StringBuffer();
while( tagMatcher.find() ) {
String closeMarker = tagMatcher.group( 1 );
String tagContent = tagMatcher.group( 2 );
//use the tagContent to do the lookup in the map and create the replacement string
String replacement = ...;
tagMatcher.appendReplacement( output, replacement );
}
tagMatcher.appendTail( output );
字符串只是一个单一的静态值。你想要的是一个从另一个字符串动态计算的字符串。
您需要将地图更改为:
Map<String, String> bbMap = new HashMap<String, String>();
对此:
Map<String, UnaryOperator<String>> bbMap = new HashMap<>();
A UnaryOperator<String>
是一个接受字符串参数和 returns 字符串值的函数。因此,您可以像这样填充地图:
bbMap.put("\[b\]", s -> "<strong>");
bbMap.put("\[/b\]", s -> "</strong>");
//...
bbMap.put("\[color=(.+?)\]", s -> "<span style='color:" + s + ";'>");
bbMap.put("\[/color\]", s -> "</span>");
bbMap.put("\[\!(.+?)\]", s -> Dialogue.pause(s));
for (Map.Entry entry : bbMap.entrySet()) {
StringBuffer buffer = new StringBuffer(html.length());
Matcher matcher =
Pattern.compile(entry.getKey().toString()).matcher(html);
while (matcher.find()) {
String match =
(matcher.groupCount() > 0 ? matcher.group(1) : null);
String replacement = entry.getValue().apply(match);
matcher.appendReplacement(buffer,
Matcher.quoteReplacement(replacement));
}
matcher.appendTail(buffer);
html = buffer.toString();
}
我正在编写标签->HTML 解析器 - 用户输入一些带有自定义标签的文本(介于 BB 和 Markdown 之间的东西,例如 [b]
或 [#RRGGBB]
),然后它正在解析到 HTML - 因此 [#FF0000]red text[/#]
变成 <span style='color:#FF0000;'>red text</strong>
,然后以 HTML 样式放置在 JTextPane 中。
所有用户标签和 HTML 存储在 HashMap 中并像这样解析:
public static String parseBBToHTML(String text) {
String html = text;
Map<String,String> bbMap = new HashMap<String , String>();
bbMap.put("\[b\]", "<strong>");
bbMap.put("\[/b\]", "</strong>");
...
bbMap.put("\[color=(.+?)\]", "<span style='color:;'>");
bbMap.put("\[/color\]", "</span>");
for (Map.Entry entry: bbMap.entrySet()) {
html = html.replaceAll(entry.getKey().toString(), entry.getValue().toString());
}
return html;
}
然后返回值用于 JTextPane 中的 .setText() 以及其他方法的动画效果,只需一个接一个地键入字母并在它们之间暂停。
一切正常,但现在我在想一件事:
我在用空 HTML 标签模仿打字动画时的暂停,如下所示:<!!!!!!!!!!>
所以 10 个“!”它们之间有 20 毫秒的停顿,给我 200 毫秒的停顿。 我正在用这个方法形成 "pause tags"(它的参数是 int,但你会明白,为什么我现在使用 String):
public static String pause(String ms){
String pausedText = "";
int time = Integer.parseInt(ms);
for (int i = 0; i < (time/animationSpeed); i++) {
pausedText = pausedText + "!";
}
return "<"+pausedText+">";
}
我想使用像 [!2000]
这样的标签来暂停 2000 毫秒。所以我只是像这样输入我的解析器字符串:
bbMap.put("\[\!(.+?)\]", Dialogue.pause(""));
...它没有用。它在方法 Dialogue.pause literally 字符串“$1”中给出,而不是 </code> 作为解析值。</p>
<p>如何使用 <code>
作为参数来形成 "pause tag" 并将其放在文本中?
在Java中$1在捕获命令之外没有特殊意义,不是全局变量。您需要解析字符串并将组捕获到局部变量中以便将来使用它。
看这里:Java Regex Replace with Capturing Group
这意味着您当前使用 bbMap 的方法不适用于这些替换。
您可以这样做:运行 首先修改您的 bbMap。然后运行第二组修改bbMap2,首先捕获组,计算长度,根据长度创建你想要的字符串,然后替换。
如果我没有记错,用你的其他代码调用 bbMap.put("\[\!(.+?)\]", Dialogue.pause(""));
你想实现这样的事情:
- 正则表达式找到组 1 的匹配项
- Dialogue.pause("$1") 使用第 1 组的内容(应该是一个数字)调用
问题是它不能那样工作,因此您可以考虑重构您的代码。与其遍历可能的标签(即 bbMap
中的条目)并在输入中查找它们,不如遍历输入,获取开始和结束标签并在地图中进行查找。
你可以用正则表达式做到这一点,但请注意,这与 HTML 有同样的问题:它不适合正则表达式,除非你真的知道数据的结构等等。
所以您可能想要做的是使用表达式查找所有标签,获取标签 name/content 然后进行替换。它可能看起来像这样:
Pattern tagPattern = Pattern.compile("\[(/?)([^\]]*)\]");
Matcher tagMatcher = tagPattern.matcher( input );
StringBuffer output = new StringBuffer();
while( tagMatcher.find() ) {
String closeMarker = tagMatcher.group( 1 );
String tagContent = tagMatcher.group( 2 );
//use the tagContent to do the lookup in the map and create the replacement string
String replacement = ...;
tagMatcher.appendReplacement( output, replacement );
}
tagMatcher.appendTail( output );
字符串只是一个单一的静态值。你想要的是一个从另一个字符串动态计算的字符串。
您需要将地图更改为:
Map<String, String> bbMap = new HashMap<String, String>();
对此:
Map<String, UnaryOperator<String>> bbMap = new HashMap<>();
A UnaryOperator<String>
是一个接受字符串参数和 returns 字符串值的函数。因此,您可以像这样填充地图:
bbMap.put("\[b\]", s -> "<strong>");
bbMap.put("\[/b\]", s -> "</strong>");
//...
bbMap.put("\[color=(.+?)\]", s -> "<span style='color:" + s + ";'>");
bbMap.put("\[/color\]", s -> "</span>");
bbMap.put("\[\!(.+?)\]", s -> Dialogue.pause(s));
for (Map.Entry entry : bbMap.entrySet()) {
StringBuffer buffer = new StringBuffer(html.length());
Matcher matcher =
Pattern.compile(entry.getKey().toString()).matcher(html);
while (matcher.find()) {
String match =
(matcher.groupCount() > 0 ? matcher.group(1) : null);
String replacement = entry.getValue().apply(match);
matcher.appendReplacement(buffer,
Matcher.quoteReplacement(replacement));
}
matcher.appendTail(buffer);
html = buffer.toString();
}