正则表达式应用退格字符

5

我从一个telnet客户端收到了一个字符串。这个字符串包含退格字符,我需要应用它们。每个退格都应该删除之前输入的一个字符。

我尝试使用正则表达式在单个替换中完成此操作:

string txt = "Hello7\b World123\b\b\b";
txt = Regex.Replace(txt, ".\\\b", "", RegexOptions.ECMAScript);

这会导致输出"Hello World12"。当然,我希望"12"也被移除,但它显然不匹配我的表达式。
某种程度上讲,应该重复替换直到没有更多匹配为止。有没有办法用一个正则表达式实现这个目标?
2个回答

4

我不建议使用正则表达式来处理这个问题,因为它非常难以理解,而且我有一种感觉,即在没有任何类似perl的魔术扩展的情况下,使用普通的正则表达式甚至不可能。我的建议是使用类似以下的Python伪代码:

stack = []
for char in str:
    if char == BACKSPACE and not stack.isEmpty():
        stack.pop()
    else:
        stack.push(char)

result = ''.join(stack)

这个功能的作用和原理非常明显。


@WouterHuysentruit:我遍历输入字符串并操作堆栈。 - Martin Thurau
+1 我明白了,谢谢。虽然我更喜欢这种方法来提高可读性,但我必须选择KennyTM的答案,因为我明确要求一个正则表达式。 - huysentruitw
2
SO:在这里你可以得到你所要求的内容,还有十几条评论告诉你为什么这是一个不好的想法! - Martin Thurau
1
好的,我们目前的代码非常类似于你的建议。但是我想知道如何用一个正则表达式来实现这个,我自己无法解决。这就是我的问题所在。 - huysentruitw
伪代码中有一个错误:如果栈为空,则将退格字符推入其中。 :) - huysentruitw
这个简单的逻辑适用于任何语言,而且速度很快;我们只需要在检查退格字符的单独条件之后检查堆栈/字符串即可。太棒了! - Christos Lytras

4
这基本上是 如何使用Java正则表达式匹配a^n b^n 的一个变体,因此我们可以重复使用那里的答案:
var regex = new Regex(@"(?:[^\b](?=[^\b]*((?>\1?)[\b])))+\1");
Console.WriteLine(regex.Replace("Hello7\b World123\b\b\b", ""));

此外,.NET正则表达式引擎支持平衡组,因此我们可以使用不同的模式:
var regex = new Regex(@"(?<L>[^\b])+(?<R-L>[\b])+(?(L)(?!))");

这意味着:

  1. 匹配一个或多个非退格字符,并将它们命名为“L”,
  2. 然后匹配一个或多个退格字符,并将它们命名为“R”,条件是每个“R”都必须有一个对应的“L”,
  3. 如果还有剩余的“L”,则放弃匹配(因为(?!)不匹配任何内容)。

)


在正则表达式中,\b 不是表示单词边界吗?如果你真的想匹配 \b,你需要转义:\\b - Buh Buh
@BuhBuh:\b在字符类中,意味着\u0008。请参阅http://msdn.microsoft.com/en-us/library/4edbef7e.aspx。 - kennytm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接