1

我试图找出一个可以处理以下条件的正则表达式:

基本上,下面的行是一对关键变量及其值,以一行文本表示。

  1. 变量名可以是 A-Za-z0-9
  2. 逗号分隔对
  3. 该值可以是任何值,包括等号和逗号

Variable1=somevalue1,Variable2=somevalue2,Variable3=some,value2

我希望有以下比赛:

  1. Variable1=somevalue1
  2. Variable2=somevalue2
  3. Variable3=some,value2

任何帮助表示赞赏,谢谢

4

4 回答 4

5

您的要求不是确定性的,因此您不会有一个结果,正则表达式也无法满足您的需求。

例如,您的样本可能有以下结果:

  • 比赛1
    • 变量 1 => 一些值 1,变量 2=一些值 2,变量 3=一些,值 2
  • 比赛2
    • 变量 1 => 某个值 1
    • 变量 2 => 一些值 2,变量 3=一些,值 2
  • 比赛3
    • 变量 1 => 某个值 1,变量 2=某个值 2
    • 变量 3 => 一些,值 2

等等。

因此,我建议考虑为值或其他类型的变量分隔提供引号。

于 2013-06-06T10:04:04.717 回答
1

有一种方法可以做到,但它不可靠,这依赖于变量必须以大写字母开头。如果值中存在 a,后跟大写字母,它也会(半)失败
([A-Z][a-zA-Z0-9]*)\s*=\s*(.*?)(?=,[A-Z]|$)

那么我们这里有什么?

  • ([A-Z][a-zA-Z0-9]*):分组并匹配以大写字母开头的字符串,并匹配零次或多次字母和数字。
  • \s*=\s*:可选地匹配空格,然后匹配等号,然后可选地匹配空格。
  • (.*?): 对所有内容进行分组和匹配,不贪心。
  • (?=,[A-Z]|$): 正向前瞻,检查是否.*?后跟 acomma and a capital letterend of line

在线演示

正则表达式很棒不是吗?

于 2013-06-06T10:26:55.763 回答
1

我通过反向遍历字符串来部分解决这个问题,从最后一个等于字符串末尾的子字符串作为值,然后对于变量名,边走边删除,然后重复直到处理完所有变量。

我必须做出一个让步,那就是如果用户想在他们的变量值中使用等号,他们必须使用一个特殊的值!!EQUALS!!然后我在变量值类中实例化值时替换它

在这个庄园中解析 1000 行的性能测试耗时 0.0019 秒。所以它很快。

string 上的 'extract' 方法是我编写的扩展方法,它输出一个子字符串,并返回原始字符串,并删除匹配的子字符串。

        public List<VariableValue> ExtractVariables(string line)
        {
            var variables = new List<VariableValue>();

            while (line != string.Empty)
            {
                // Get the value 
                var value = string.Empty;
                var lastEquals = line.LastIndexOf('=') + 1;
                line = line.Extract(lastEquals, line.Length - lastEquals, out value);

                // Get the variable
                var variable = string.Empty;
                var lastComma = line.LastIndexOf(',') + 1;
                line = line.Extract(lastComma, line.Length - lastComma - 1, out variable);

                // Add to list of results
                variables.Add(new VariableValue(variable, value));

                // Remove the trailing bits
                line = (line == "=")
                           ? string.Empty
                           : line.Remove(line.LastIndexOf(','), line.Length - line.LastIndexOf(','));
            }

            variables.Reverse();
            return variables;
        }

你觉得我的解决方案怎么样?

于 2013-06-06T11:02:51.623 回答
1

显然,包含您的分隔符的值是有问题的。

但是,只要您的密钥不能包含这些分隔符,就可以合理地处理它们。秘制酱汁的配方是这样的:

/(?:,|^)(?=[^,]+=)/

首先,我们断言字符串有逗号或开头,后面没有逗号,直到下一个等号。实际上,这会拆分给定键/值对中的最后一个逗号。

然后我们只是循环结果并在第一个等号上拆分。

所以我们最终得到(显然翻译成你选择的语言,我用过 PHP,但重要的是逻辑):

<?php

    $str = 'Variable1=somevalue1,Variable2=somevalue2,Variable3=some,value2';

    $result = [];
    foreach (preg_split('/(?:,|^)(?=[^,]+=)/', $str, -1, PREG_SPLIT_NO_EMPTY) as $item) {
        $item = explode('=', $item, 2);
        $result[$item[0]] = isset($item[1]) ? $item[1] : '';
    }

    print_r($result);

产生:

Array
(
    [Variable1] => somevalue1
    [Variable2] => somevalue2
    [Variable3] => some,value2
)

看到它工作

于 2013-06-06T11:05:32.620 回答