2

我得到一个 15 位的输入字符串,即001230123456789. 它有两个数字 - 第一个是00123(最少 1 个非零数字,最多 5 个数字),第二个是0123456789(最少10000000010 个数字)。捕获的输出(这些数字)不应包含前导零。

更容易并且可能是唯一正确的方法(在 Python 中)是数组切片和 lstrip():

input = "001230123456789"
output = [(input[:5].lstrip('0'), input[5:].lstrip('0'))]
# ('123', '123456789')

但我有一个任务是用正则表达式做同样的事情。

无论我是否尝试过贪婪的选项,我都坚持留下 zome zeros。我已经以那个结束了:0{0,4}([1-9]\d{0,4})0?([1-9]\d{8,9}) 它通过了我 3/6 的测试:

000010111111111 -    ('10', '111111111')     (should be ('1', '111111111'))
116402151672479 - OK ('11640', '2151672479')
006421651672479 -    ('6421', '651672479')   (should be ('642', '1651672479'))
712120751672479 - OK ('71212', '751672479')
712121551672479 - OK ('71212', '1551672479')
006400351672479 -    ('6400', '351672479')   (should be ('640', '351672479'))

有没有办法只用一个正则表达式来做到这一点?

paste.org上带有测试和预期值的完整示例源代码。

4

4 回答 4

4

干得好。

    /^0*(\d{1,5})(?<=.{5})(?<!00000)(?!00)(?=\d{10}$)0*(.+)/
      | |        |        |         |     |          | |
      | |        |        |         |     |          | capture 2nd number
      | |        |        |         |     |          |
      | |        |        |         |     |          chomp leading zeroes
      | |        |        |         |     |
      | |        |        |         |     assert there're 10 digits ahead
      | |        |        |         |
      | |        |        |         assert second part at least 100000000
      | |        |        |
      | |        |        make sure first part at least one nonzero digit
      | |        |
      | |        assert there are 5 chars behind (already tested numeric)
      | |
      | capture 1st number (don't worry; the assertions will fix this up)
      |
      chomp leading zeroes (i'm going to line up these comments damn it!)

这是一个 Rubular 演示

(?:^|\s)(?:\s|$)仅用于演示目的。)

结果如下:

    000010111111111             -->     1       111111111
    116402151672479             -->     11640   2151672479
    006421651672479             -->     642     1651672479
    712120751672479             -->     71212   751672479
    712121551672479             -->     71212   1551672479
    006400351672479             -->     640     351672479

    # not enough digits        
    71212155167247              -->     no match

    # too many digits          
    7121215516724798            -->     no match           

    # first part == 0          
    000001551672479             -->     no match            

    # second part < 100,000,000
    712120098765479             -->     no match
于 2012-09-07T21:21:08.520 回答
3

我对 python 不是很熟悉,但是下面的解决方案(perl)将完全符合您的要求;虽然它很丑。

use strict;

my @test = qw/000010111111111 116402151672479 006421651672479 712120751672479 712121551672479 006400351672479/;

foreach(@test){
    /^(?|([1-9]\d{4})|0([1-9]\d{3})|00([1-9]\d{2})|000([1-9]\d)|0000([1-9]))(?|0([1-9]\d{8})|([1-9]\d{9}))/;
    print "$_: ($1, $2)\n";
}

exit 0;

快速浏览一下 python re 页面,我没有(?|...)明确看到,但它确实有(?:...). 在这种情况下,您将获得一个匹配数组,其中只有两个非空白条目——这将是您的答案。

于 2012-09-07T19:03:06.037 回答
2

试试这个 Python 正则表达式:

0{0,4}(\d+)(?<=^\d{5})0{0,9}(\d+)
|     |    |          |     |
|     |    |          |     Second number without leading zeros
|     |    |          Up to 9 leading zeros of second number
|     |    Must be preceded by start of string and 5 digits
|     First number without leading zeros
Up to 4 leading zeros of first number
于 2012-09-07T23:37:18.540 回答
2

这是我的解决方案:

re.search(r'([1-9]\d*)(?=\d{10})0*([1-9]\d*)', "0064000351672479").groups()
# ('640', '351672479')

分解:

  • ([1-9]\d*)- 第一组,必须从 1-9 开始,
  • (?=\d{10})- 展望未来,我们有 10 个数字,
  • 0* - 从第二个数字开始咀嚼领导者零,
  • ([1-9]\d*)- 第二组(数字)。
于 2012-09-12T07:50:21.403 回答