代码之家  ›  专栏  ›  技术社区  ›  Sinister Beard

RE2中指定字符前后是否有匹配的方法?

  •  0
  • Sinister Beard  · 技术社区  · 6 年前

    我需要在更大的文档中找到可能是信用卡详细信息的数字,例如。 346490606109917 . 我想忽略其中包含信用卡风格细节的较大数字,例如。 96213464906061099171 .

    在普通的正则表达式中(如果你能原谅双关语的话),我可以使用 (?<![0-9]) 在模式开始时 (?![0-9]) 最后,这样只匹配与信用卡格式完全匹配的号码,而其中可能包含信用卡样式号码的较大号码将被忽略。数字两边的非数字字符都可以。

    我的模式是

    (?<![0-9])(4[0-9]{12}(?:[0-9]{3})?|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})(?![0-9])
    

    在正常的正则表达式中 abc346490606109917zyz 但不是在 abc96213464906061099171xyz ,例如。

    然而, this isn't supported in Regex2 ,这就是BigQuery使用的功能—在文档中它被列为“不受支持”。

    RE2中是否有等效物,或不可能?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Mikhail Berlyant    6 年前

    下面是BigQuery标准SQL

    #standardSQL
    WITH `project.dataset.table` AS (
      SELECT 'abc346490606109917zyz' str UNION ALL
      SELECT 'abc96213464906061099171xyz'
    )
    SELECT *, REGEXP_CONTAINS(str, r'(^|[^0-9])(4[0-9]{12}(?:[0-9]{3})?|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})($|[^0-9])') check
    FROM `project.dataset.table`   
    

    结果如下

    Row str                         check    
    1   abc346490606109917zyz       true     
    2   abc96213464906061099171xyz  false      
    

    这个 (^|[^0-9]) 部分标识字符串的开头或非数字序列。同样适用于 ($|[^0-9]) 但它不表示开始,而是表示字符串结束或非数字序列

    如果您还需要提取卡号,请使用下面的示例

    #standardSQL
    WITH `project.dataset.table` AS (
      SELECT 'abc346490606109917zyz' str UNION ALL
      SELECT 'abc96213464906061099171xyz'
    )
    SELECT *, 
      REGEXP_CONTAINS(str, r'(^|[^0-9])(4[0-9]{12}(?:[0-9]{3})?|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})($|[^0-9])') check,
      REGEXP_EXTRACT(str, r'(?:^|[^0-9])(4[0-9]{12}(?:[0-9]{3})?|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})(?:$|[^0-9])') number
    FROM `project.dataset.table`   
    

    结果将是

    Row str                         check   number   
    1   abc346490606109917zyz       true    346490606109917  
    2   abc96213464906061099171xyz  false   null        
    

    在这里,在 REGEXP_EXTRACT 你需要使用 (?:regular_expression) 指示非捕获组