【问题标题】:Find substrings that start and end with same Uppercase Character查找以相同大写字符开头和结尾的子字符串
【发布时间】:2019-05-10 21:28:43
【问题描述】:

我有一个作业问题,我需要使用正则表达式来解析大字符串中的子字符串。

目标是选择匹配以下参数的子字符串:

子字符串以相同的大写字符开始和结束,我需要忽略任何前面带有数字 0 的大写字符的实例。

例如,ZAp0ZuZAuX0AZA 将包含匹配 ZAp0ZuZAuX0AZA

我已经搞砸了几个小时,老实说,我什至没有接近...

我尝试了一些类似下面的代码的东西,但它会选择从第一个大写到最后一个大写的所有内容。我也有

[A-Z]{1}[[:alnum:]]*[A-Z]{1} <--- this selects the whole string
[A-Z]{1}[[:alnum:]][A-Z]{1} <--- this gives me strings like ZuZ, AuX

真的很感谢任何帮助,我完全被这个难住了。

【问题讨论】:

  • 您好!你愿意分享你的尝试吗?这样,我们可以确保我们不会为您从火中拔出栗子。
  • 我不确定你在做什么,但这不是 python。 Python 字符类的写法不同。
  • @MegaIng [[:alnum:]] 受 PyPi 正则表达式模块支持,但 Ryan 没有提供任何正则表达式库详细信息。
  • @WiktorStribiżew 我不知道。谢谢!
  • Ryan,请查看我的回答,如果您需要更多指导,请告知。

标签: python regex regex-lookarounds regex-group regex-greedy


【解决方案1】:

使用正则表达式可能不是最好的主意,因为您可以简单地拆分它们。但是,如果您有/希望这样做,this expression 可能会让您了解当您的字符列表扩展时您可能会遇到什么问题:

(?=.[A-Z])([A-Z])(.*?)\1

我添加了(?=.[A-Z]),它必须包含一个大写字母。你可以删除它,它会工作。但是,为了安全起见,您可以在表达式中添加此类边界。

JavaScript 测试

const regex = /([A-Z])(.*?)\1/gm;
const str = `ZAp0ZuZAuX0AZA
ZApxxZuZAuXxafaAZA
ZApxaf09xZuZAuX090xafaAZA
abcZApxaf09xZuZAuX090xafaAZA`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

Python 测试

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"([A-Z])(.*?)\1"

test_str = ("ZAp0ZuZAuX0AZA\n"
    "ZApxxZuZAuXxafaAZA\n"
    "ZApxaf09xZuZAuX090xafaAZA\n"
    "abcZApxaf09xZuZAuX090xafaAZA")

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):
    
    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))
    
    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1
        
        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

【讨论】:

    【解决方案2】:

    这可能有效

    (?&lt;!0)([A-Z]).*?(?&lt;!0)\1

    https://regex101.com/r/nES9FP/1

    解释

     (?<! 0 )      # Ignore Upper case with zero in front of it
     ( [A-Z] )     # (1), This Upper case is to be found down stream
     .*?           # Lazy, any character
     (?<! 0 )      # Ignore Upper case with zero in front of it
     \1            # Backref to what is in group (1)
    

    【讨论】:

      【解决方案3】:

      你可以使用

      (?<!0)([A-Z]).*?(?<!0)\1
      

      请参阅regex demo

      详情

      • (?&lt;!0)([A-Z]) - 第 1 组:ASCII 大写字母,前面不带零
      • .*? - 尽可能少的除换行符以外的任何字符
      • (?&lt;!0)\1 - 与第 1 组中相同的字母,前面没有紧跟 0

      Python demo

      import re
      s="ZAp0ZuZAuX0AZA"
      for m in re.finditer(r'(?<!0)([A-Z]).*?(?<!0)\1', s):
          print(m.group()) # => ['ZAp0ZuZ', 'AuX0AZA']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-20
        • 2015-11-08
        相关资源
        最近更新 更多