【问题标题】:RegEx to extract the first 6 to 10 digit number, excluding 8 digit numbersRegEx 提取前 6 到 10 位数字,不包括 8 位数字
【发布时间】:2018-04-17 01:16:15
【问题描述】:

我有以下测试文件名:

abc001_20111104_summary_123.txt
abc008_200700953_timeline.txt
abc008_20080402_summary200201573unitf.txt
123456.txt
100101-100102 test.txt
abc008_20110902_summary200110254.txt
abcd 200601141 summary.txt
abc008_summary_200502169_xyz.txt

我需要从每个文件名中提取一个数字

号码必须为 6、7、9 或 10 位数字(因此,不包括 8 位数字)。

如果找到多个,我想获得第一个数字,如果没有找到,我想获得空字符串。

我设法在 2 步过程中做到了这一点,首先删除 8 位数字,然后从我的列表中提取 6 到 10 位数字。

step 1 
  regex:  ([^0-9])([0-9]{8})([^0-9])
  replacement:  \1\3

step 2
  regex: (.*?)([1-9]([0-9]{5,6}|[0-9]{8,9}))([^0-9].*)
  replacement:  \2

在这 2 步过程之后得到的数字正是我想要的:

[]
[200700953]
[200201573]
[123456]
[100101]
[200110254]
[200601141]
[200502169]

现在,问题是: 有没有一种方法可以一步完成?

我看到this nice solution 回答了一个类似的问题,但是,如果找到多个,它会给我最新的号码。

注意:使用The Regex Coach进行测试。

【问题讨论】:

  • 指定你的编程语言会很有帮助。

标签: c# regex


【解决方案1】:

假设您的正则表达式引擎支持后向断言:

(?<!\d)\d{6}(?:\d?|\d{3,4})(?!\d)

说明:

(?<!\d)   # Assert that the previous character (if any) isn't a digit
\d{6}     # Match 6 digits
(?:       # Either match
 \d?      # 0 or 1 digits
|         # or
 \d{3,4}  # 3 or 4 digits
)         # End of alternation
(?!\d)    # Assert that the next character (if any) isn't a digit

【讨论】:

  • 谢谢,蒂姆!这解决了这个问题。也谢谢你的解释。不过,我最终使用了您的解决方案的修改版本,因为在某些情况下,我必须提取一个范围或第二个数字,或两者兼而有之,但您提供的部分没有受到影响。 :)
【解决方案2】:

试试这个:

regex: /(?:^|\D)(\d{6}(?:\d(?:\d{2,3})?)?)(?:\D|$)/
replacement: \1

这将提取六位数字,可选地后跟一位(总共 7 个),可选地后跟 2 或 3 个(9 或 10)。

【讨论】:

    【解决方案3】:

    对于每个字符串 $subject

    $subject = "abc001_20111104_summary_123.txt";
    $subject ="abc008_200700953_timeline.txt";
    $subject ="abc008_20080402_summary200201573unitf.txt";
    $subject ="123456.txt"
    $subject ="100101-100102 test.txt"
    $subject ="abc008_20110902_summary200110254.txt";
    $subject ="abcd 200601141 summary.txt";
    $subject ="abc008_summary_200502169_xyz.txt";
    
    $pattern = '*(?<!\d)(\d{6,7}|\d{9,10})(?!\d)*';
    preg_match_all($pattern, $subject, $matches);
    print_r($matches);
    

    你得到了预期的结果:

    • 200700953
    • 200201573
    • 123456
    • 100101
    • 200110254
    • 200601141
    • 200502169

    【讨论】:

      【解决方案4】:

      [0-9]{6,7}|[0-9]{9,10} 的边缘匹配单词边界或非数字应该这样做:

      ([^0-9]|\<)([0-9]{6,7}|[0-9]{9,10})([^0-9]|\>)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多