复杂的正则表达式来处理数字序列

时间:2014-03-01 10:24:29

标签: regex numbers

嗨,我一直处理一个困难的正则表达式来处理我的知识非常有限。如果有人能让我理解如何解释这样的问题,那就太棒了:

描述: 给定一串数字,如1234567,我将得出一个正则表达式,将结果输出为:

12
23
34
45
56
67

我不是要求直接解决方案,而是指南会很棒。

4 个答案:

答案 0 :(得分:1)

你没有说明你正在使用哪种语言,但我认为它支持积极的前瞻 - 大多数都是这样做的。

以下是Java中的解决方案:

public static void main(final String[] args) throws Exception {
    final String in = "1234567";
    final Pattern patt = Pattern.compile("(?=(\\d{2})).");
    final Matcher matcher = patt.matcher(in);
    while (matcher.find()) {
        System.out.println(matcher.group(1));
    }
}

输出:

12
23
34
45
56
67

模式为(?=(\d{2})).(出于语言语法原因,您需要Java中的\\)。

说明:

  • (?=(\d{2}))这是解决方案的核心,它有点棘手,它是一个积极的先行断言,检查输入String中当前点之后的两位数。然后它抓住这两个数字 - 这就是“输出”的来源。
  • .这匹配任何字符(也可能是\d,但这不是必需的)。这可以确保正则表达式引擎一次沿着一个空格移动。

所以最初引擎是String的开头。断言捕获12.捕获并消耗 1。现在引擎位于1之后,断言捕获23.捕获并消费 2。等...

诀窍是断言一次捕获两个字符,但模式一次只能推进一个字符。

这个单行代码执行替换而不是搜索 - 在Java String中是不可变的,因此结果实际上是不同的String - String in不会被操作修改:

public static void main(final String[] args) throws Exception {
    System.out.println("1234567".replaceAll("(?=(\\d{2})).(?=\\d{2})", "$1\n"));
}

这里我们需要添加另一个断言,即在此之后至少要再消耗两个数字。输出:

12
23
34
45
56
67

答案 1 :(得分:1)

在perl中,您可以:

echo 1234567|perl -ne 's/(?<!^)(.)(?!$)/$1\n$1/g; print;'

(?<!^)negative look-behind assertion(用于字符串^的开头)。 (?!$)是一个负面的前瞻断言(对于字符串$的结尾)。正则表达式将匹配除第一个和最后一个之外的所有字符。替换重复匹配的字符,中间有换行符。

答案 2 :(得分:1)

这与Perl one liner一样:

echo 1234567 | perl -ne "$\=$/; print for $_=~/(?=(\d\d))/g"

答案 3 :(得分:0)

正则表达式不会输出任何内容,它会找到匹配的文本。我猜你的'输出'实际上是所有比赛的列表。

所以你需要一个能在搜索文本中找到所有这些数字对的正则表达式。