正则表达式 - 匹配相同模式的组

Posted

技术标签:

【中文标题】正则表达式 - 匹配相同模式的组【英文标题】:Regex - groups matching same pattern 【发布时间】:2013-11-25 02:10:23 【问题描述】:

我正在尝试使用 C# 匹配相同模式的正则表达式组。 这是一个我无法开始工作的小例子。

我需要获取所有单引号之间的字符串(例如 CodigoEmpresa)

uses MainRecord, objErrorList, SysUtils, XMLMXMWebServiceReturn, objMainProcesso,
 objProcessoWS, objProcessaRelatorioQuickReport, QuickRpt, Forms,
 RBalanc, RBalancete, RBaCCMens, RBalaMensal, RBalaMensalCons,
 objcadcontabilidade, objContabilidadeValidacoes;

const
CODIGO_EMPRESA             = 'CodigoEmpresa';
ANO_MES                    = 'AnoMes';
RELATORIO_POR              = 'RelatorioPOR';
CONTA_INI                  = 'ContaIni';
CONTA_FIM                  = 'ContaFim';
GRAU_CONTA                 = 'GrauConta';
CCUSTOS_INI                = 'CCustosIni';
CCUSTOS_FIM                = 'CCustosFim';
GRAU_CCUSTOS               = 'GrauCCustos';
DETALHAR_CONSOLIDADO       = 'DetalharConsolidado';
DESCONSIDERAR_ENCERRAMENTO = 'DesconsiderarEncerramento';
QUEBRA_CCUSTO              = 'QuebraCCusto';
CONTAS_SEM_MOVIMENTO       = 'ContasSemMovimento';
CODIGO_ALTERNATIVO         = 'CodigoAlternativo';

const

ERROR_BALANCETE_MENSAL_0001 = 'BALANC0001';
ERROR_BALANCETE_MENSAL_0002 = 'BALANC0002'; //Empresa Inexistente
ERROR_BALANCETE_MENSAL_0003 = 'BALANC0003';
ERROR_BALANCETE_MENSAL_0004 = 'BALANC0004';
ERROR_BALANCETE_MENSAL_0005 = 'BALANC0005';
ERROR_BALANCETE_MENSAL_0006 = 'BALANC0006';
ERROR_BALANCETE_MENSAL_0007 = 'BALANC0007';
ERROR_BALANCETE_MENSAL_0008 = 'BALANC0008';

到目前为止我已经尝试过了:

Match match = Regex.Match(delphiFileInText, @"const.+=\s*'(?<property>[\d\w]+)'", RegexOptions.IgnoreCase | RegexOptions.Singleline);

但我得到的只是最后一场比赛(BLANC0008);

我希望我能说清楚。感谢您的帮助

【问题讨论】:

你需要更清楚你希望匹配什么模式,以及你需要什么捕获。 这没有多大意义 显示您的代码,更具体地说明您想要什么、尝试过什么、出了什么问题等。 你需要第一个 .+ 是非贪婪的。我想使用CONST.+?(EST)ING+CONST(.+(EST)ING+)? 我也怀疑你是否试图匹配 1-many Gs 最后。这就是 G+ 正在做的事情,允许 TESTINGGGGGGG。虽然自从它的G+? (不贪心),并且在模式的末尾,无论如何它都等同于 G。 【参考方案1】:

只需将您的表达式替换为

'(?<property>[\d\w]+)'

将获得所有这些。

【讨论】:

【参考方案2】:

我建议使用以下正则表达式:

'(?<property>(?:\\'|[^'])*)'

这将捕获输入中所有单引号分隔的字符串。如果您还想捕获常量,我建议使用以下正则表达式:

(?<const>\w+)\s*=\s*'(?<property>(?:\\'|[^'])*)'

【讨论】:

我稍微改了一下。最终版本是:[A-Z_]*\s*=\s*'(?(?:\\'|[^'])*)'。这样我可以根据大写常量获取字符串。您的回答很完美,我刚刚根据我的具体情况对其进行了调整。谢谢大家。【参考方案3】:

似乎为了做你想做的事,你真的不需要正则表达式,而是可以逐个字符地浏览文件并以这种方式解析它。这比试图找出正则表达式要容易得多,而且它不会是“只读的”(这意味着当你稍后回到代码时,你会确切地知道该怎么做。这是我烘焙的一个类为此(我尚未对其进行全面测试,但确实对示例字符串进行了快速测试,它的工作原理与那里的广告一样):

public class Parser

    bool inQuotes;
    public Parser()
    
        inQuotes = false;
    

    public List<string> Parse(string input)
    
        List<string> output = new List<string>();
        StringBuilder temporaryString = new StringBuilder();
        for (int i = 0; i < input.Length; i++)
        
            if (input[i] == '\'' && !inQuotes)
            
                inQuotes = true;
                continue;
            
            else if (input[i] == '\'' && inQuotes)
            
                output.Add(temporaryString.ToString());
                inQuotes = false;
                temporaryString = new StringBuilder();
            
            else if (inQuotes)
            
                temporaryString.Append(input[i]);
            
        
        return output;
    

此代码将逐个字符地遍历,当它遇到一个单引号时,它将开始“保存”字符串,直到它遇到另一个单引号。它将忽略所有其他字符,只关注单引号内的字符。最重要的是,您可以对其进行调整以允许嵌套引号相当容易。

【讨论】:

“正则表达式很难”是一个糟糕的借口。它们是一个强大的工具,背后有大量的时间和专业知识。它们通常针对他们正在做的事情进行了高度优化,并且可以像任何其他实现一样以可维护和不可维护的方式编写。它们只是有限状态机——有点像你在这里的答案,可以正则表达式为'[^']*',以备记录。这似乎比你写的更容易维护。

以上是关于正则表达式 - 匹配相同模式的组的主要内容,如果未能解决你的问题,请参考以下文章

获取在正则表达式中匹配的组的索引?

正则表达式匹配匹配的组并将其存储在数组中

正则表达式中 ?,+,*,{}的运用

java正则表达式匹配IP地址和端口号作为捕获的组

正则表达式 Match.Value 返回整个值,而不是匹配的组

Boost 正则表达式:获取命名组