我有一个由用户键盘类型构造的字符串,因此它可能包含 '\b'
字符(退格)。
我想清理字符串,以便它不会包含 '\b'
字符,以及它们要删除的字符。例如,字符串:
String str = "\bHellow\b world!!!\b\b\b.";
应打印为:
Hello world.
我用replaceAll尝试过一些东西,我现在拥有的是:
System.out.println(str.replaceAll("^\b+|.\b+", ""));
哪个印刷品:
你好,世界!!。
单 '\b'
处理正常,但忽略它的倍数。
那么,我可以用Java的正则表达式来解决它吗?
编辑:
我见过 这个 回答,但它似乎不适用于java的replaceAll。
也许我错过了逐字字符串的东西......
它不能在一次通过中完成,除非对连续退格的数量有实际限制(没有),并且有一个保证(没有)没有“额外”退格其中没有要删除的前一个字符。
这样做(它只有2条小线):
while (str.contains("\b"))
str = str.replaceAll("^\b+|[^\b]\b", "");
这处理输入的边缘情况 "x\b\by"
它在开始时有一个额外的退格,一旦第一个退出消耗,应该修剪 x
只留下 "y"
。
你试图解决的问题无法解决 单 正则表达式。问题在于语法,它产生语言 {any_symbol}*{any_symbol}^n{\b}^n
(这是您输入的特例)不是 定期。你需要在某个地方存储状态(之前有多少符号) \b
和 \b
它已阅读),但DFA无法做到(因为DFA无法知道它能找到多少顺序\ b)。所有提议的解决方案都只适用于您的情况("\bHellow\b world!!!\b\b\b."
)并且可以通过更复杂的测试轻松破解。
最简单的解决方案是替换周期对{除了\ b}之外的所有{\ b}
UPD: 解决方案,由提出 @Bohemian 似乎完全正确:
UPD 2:
好像java的正则表达式可以解析 不仅是常规语言,还有像 {a}^n{b}^n
使用递归前瞻,所以在java的情况下,可以将这些组与单个正则表达式匹配。
感谢@Pshemo评论和@Elist编辑!
这看起来像是一份工作 堆!
Stack<Character> stack = new Stack<Character>();
// for-each character in the string
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// push if it's not a backspace
if (c != '\b') {
stack.push(c);
// else pop if possible
} else if (!stack.empty()) {
stack.pop();
}
}
// convert stack to string
StringBuilder builder = new StringBuilder(stack.size());
for (Character c : stack) {
builder.append(c);
}
// print it
System.out.println(builder.toString());
正则表达式虽然不错,但并不适合所有任务。这种方法并不简洁 波西米亚的,但效率更高。在每种情况下使用堆栈都是O(n),而像Bohemian这样的正则表达式是O(n2)在最坏的情况下。
如果我正确理解了这个问题,这就是你问题的解决方案:
String str = "\bHellow\b world!!!\b\b\b.";
System.out.println(str.replace(".?\\\b", ""));
这是一个很好的谜语。我认为你可以使用正则表达式 删除相同数量的相同重复字符和 \b
小号 (即对于您的特定输入字符串):
String str = "\bHellow\b world!!!\b\b\b.";
System.out.println(str.replaceAll("^\b+|(?:([^\b])(?=\\1*+(\\2?+\b)))+\\2", ""));
这是一个改编 我们怎样才能将^ n b ^ n与Java正则表达式匹配?。
看到 IDEONE演示,我添加了 .replace("\b","<B>"));
看看有没有 \b
离开了。
输出:
Hello world.
一般的正则表达式解决方案不在正则表达式范围内......现在。