使用正则表达式标识逗号中的空格

时间:2014-06-05 17:23:45

标签: regex

我有一个用空格分隔的数据,但其中一个数据有逗号的特殊格式。

例如:

A B C,D,E,F G H

使用“[^ \ s] + \,”检测逗号组的开头,并且组的末尾带有“\,[^ \ s +]”。 在此示例中,逗号组以“C”开头,以“,F”结尾。逗号的数量不止一个。 只有一个逗号组,但位置可能会有所不同。

我可以使用\s+分隔5个数据组([A],[B],[C,D,E,F],[G],[H]),但问题在于那里可以是数据组中包含逗号的数据中的空格。

例如:

A B C,D E F,G H I,J K L M

逗号前后没有空格。

在这种情况下,我们有6组([A],[B],[C,D E F,G H I,J],[K],[L],[M])。

如何使用正则表达式获得此结果?我正在使用Python和Scala。

5 个答案:

答案 0 :(得分:3)

明确的答案取决于你的口味,但这里有一个正则表达式,它将分别匹配"逗号"组和非逗号组。逗号组进入捕获比赛1;非逗号组进入第2组

(\S+,.*,\S+)|(\S+)

答案 1 :(得分:0)

注意: 这只适用于PCRE。

\G[^,]+?\K\s+|(?:(?!.*,)\s)+

Demo


第一组(逗号之前)使用两个仅限PCRE的快捷方式(\G\K)来解决这样一个事实,即我们无法进行可变长度的后视制作确保比赛前没有逗号。这是如何工作的\G从字符串的开头或最后一个匹配的结尾开始,只要没有逗号,我们就会继续,抛弃与\K匹配的所有内容,然后匹配我们的空白。一旦我们点击第一个逗号,这将不再匹配,我们将落入第二组。

第二组(逗号后)使用重复的负向前瞻。只要表达式前面没有逗号,它就会匹配一个空白字符。换句话说,这只会匹配最后一个逗号后面的空格。这两个组将保留逗号组中未触及的任何空格。

(?# BEFORE THE COMMA GROUP)
\G      (?# the beginning of the string OR end of last match)
[^,]+?  (?# lazily match non-comma characters)
\K      (?# throw away everything to the left)
\s+     (?# match 1+ whitespace)

|        (?# OR)

(?# AFTER THE COMMA GROUP)
(?:     (?# start non-capturing group for repetition)
  (?!   (?# start negative lookahead)
    .*, (?# look for a comma)
  )     (?# end negative lookahead)
  \s    (?# match whitespace)
)+      (?# repeat group 1+ times)

答案 2 :(得分:0)

尝试使用:([A-Z],(.*){2}?,[A-Z])|\s+

您没有指定语言,但这里有一个C#示例,根据您的问题和所需的输出将字符串拆分为组。

static void Main(string[] args)
{
    string t = "A B C,D E F,G H I,J K L M";
    Console.WriteLine(t);
    var r = Regex.Split(t, @"([A-Z],(.*){2}?,[A-Z])|\s+");
    foreach (string s in r)
    {
        if (string.IsNullOrEmpty(s))
            continue;
        Console.WriteLine(s);
    }

    Console.ReadKey();
}

输出如下:

A B C,D E F,G H I,J K L M
A
B
C,D E F,G H I,J
K
L
M

答案 3 :(得分:0)

如果您在后台使用正则表达式引擎支持无限重复,那么以下正则表达式适用于拆分操作。

(?<!,.*)\s+|\s+(?!.*,)

Regular expression visualization

但是由于你使用Python和Scala并且它们不支持lookbehind中的无限重复,所以以下内容可能对你有用(选择所有匹配)。

\w,\w.*\w,\w|\w

Regular expression visualization

<强> Demo

答案 4 :(得分:0)

这是一个可以在Python中运行的简单解决方案的两个版本。见demo

[A-Z](?:,(?:.*,)?[A-Z])?

如果需要,请将[A-Z]替换为更复杂(但仍然具体)的内容,例如\S(请参阅demo):

\S(?:,(?:.*,)?\S)?

它是如何运作的?

  1. [A-Z]\S与您的令牌的第一个字符匹配。
  2. 可选的非捕获组(?: ... )?与令牌的其余部分(逗号部分)匹配(如果存在)。
  3. 在该组,(?:.*,)?[A-Z]中,我们匹配第一个逗号,然后贪婪但可选(?:.*,)?匹配任何字符,直到最后一个逗号(如果有另一个逗号),则{{1 }}或[A-Z]匹配最后一个逗号后的字符。