gpt4 book ai didi

java - 使用Java正则表达式匹配前面没有百分号的字母字符

转载 作者:行者123 更新时间:2023-11-30 01:50:40 27 4
gpt4 key购买 nike

tl;博士:

我想采用如下字符串:ab%cde%fg hij %klm n%op

并将其转换为以下任意一种(都可以接受):

  • 'ab'%c'de'%f'g hij '%k'lm n'%o'p'
  • 'ab'%c'de'%f'g' 'hij' %k'lm' 'n'%o'p'
  • 'a''b'%c'd''e'%f'g' 'h''i''j' %k'l''m' 'n'%o'p'

(如果字母字符前面没有 %,则它需要位于单引号内。打开和关闭额外的单引号是可以接受的)

用例

我正在尝试在 C strftime format 中获取一个字符串并将其转换为与 Java 的 SimpleDateFormat 一起使用。在大多数情况下,这非常简单:

String format = "%y-%m-%d %H:%M:%S";

Map<String, String> replacements = new HashMap<String, String>() {{
put("%a", "EEE");
put("%A", "EEEE");
put("%b", "MMM");
put("%B", "MMMM");
put("%c", "EEE MMM dd HH:mm:ss yyyy");
// ... for each strftime token, create a mapping ...
}};

for ( String key : replacements.keySet() )
{
// apply the mappings one at a time
format = format.replaceAll(key, replacements.get(key));
}

// Then format
SimpleDateFormat df = new SimpleDateFormat(format, Locale.getDefault());
System.out.println(df.format(Calendar.getInstance().getTime()));

但是,当我引入字 rune 字时,它遇到了问题。根据 strftime 文档,前面没有百分号的所有字 rune 字都会在不修改输出字符串的情况下传递。所以:

Format: "%y is a great year!"
Output: "2019 is a great year!"

但是,使用 SimpleDateFormat 时,所有字 rune 字都被视为标记,除非用单引号引起来:

Format: "yyyy 'is a great year!'"
Output: "2019 is a great year!"

Format: "yyyy is a great year!"
Output: ERROR - invalid token "i"

期望的输出

因为 strftime 标记始终是单个字符,所以修复我们的格式字符串应该不会太困难。在最坏的情况下,“如果字母前面没有 % 符号,则将其用单引号引起来”,这将导致:

Format: "%y is a great year!"
Processed: "%y 'i''s' 'a' 'g''r''e''a''t' 'y''e''a''r'!"

这很丑陋,但会按预期运行,并且是一个可以接受的答案。理想情况下,我们会包装所有前面没有%的字母字符,如下所示:

Format: "%y is a great year!"
Processed: "%y 'is' 'a' 'great' 'year'!"

或者,更好的是,所有运行包括非字母和非 % 字符:

Format: "%y is a great year!"
Processed: "%y' is a great year!'"

我尝试过的

我从一个盲目的正则表达式开始,我很确定它不会起作用,但它没有:

format.replaceAll("[^%]([a-zA-Z]+)", "'$1'");
// Format: "Literal %t Literal"
// Output: "'iteral' %t'Literal'"
// Expected: "'Literal' %t 'Literal'"

我对反向引用没有牢固的把握,所以我尝试了一下,但也弄乱了一些东西:

format.replaceAll("(?!%)([a-zA-Z]+)", "'$1'");
// Format: "Literal %t Literal"
// Output: "'Literal' %'t' 'Literal'"
// Expected: "'Literal' %t 'Literal'"

我还考虑过编写一个非常简单的词法分析器。像这样的东西:

StringBuffer s = new StringBuffer();
boolean inQuote = false;
for (int i = 0; i < format.length; i++)
{
if (format[i] == '%')
{
i++;
s.append(replacements.get(format[i]);
}
else if (inQuote)
{
s.append(format[i]);
}
else
{
s.append("'");
inQuote = true;
s.append(format[i]);
}
}

但是我了解到 format[i] 不是有效的 Java 语法,并且在我决定在这里发布之前没有花太多时间研究如何正确地从字符串中获取字符.

我更喜欢正则表达式解决方案,这样我就可以将其写在一行中,而不是像这样的循环。

最佳答案

它已更新为可使用单个正则表达式。可以添加其他格式来测试正确性。

      String[] formats = { "ab%cde%fg hij %klm n%op", "ab%c", "%d"
};
for (String f : formats) {
String parsed = f.replaceAll("(^[a-z]+|(?<=%[a-z])([a-z ]+))", "'$1'");
System.out.println(parsed);
}

两种可能性是:

  • %[a-z] 后面的所有字符 [a-z]+ 放在单引号之间。
  • % 之前且上面未包含的任何字符放置在单引号。

关于java - 使用Java正则表达式匹配前面没有百分号的字母字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56175777/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com