正则表达式帮助:逗号分隔列表

时间:2011-04-26 15:14:22

标签: php regex

我正在尝试(在php中)

  
      
  1. 验证textarea的内容是否有效
  2.   
  3. 将它们分成令牌以进行处理
  4.   

为了被认为是有效的,它必须是一个只包含数字和字母的字符串,这些数字和字母形成一个长度为3-6的“代码”,用于分隔它们的逗号。我把它分解成了这样的东西:

[A-Za-z0-9]{3,6},

我很难完成它。我希望它们能够用逗号,空格和逗号空格,逗号空间等分开。我只希望有一个逗号,如果有以下有效标记。

例如,输入字符串:

  

abe 123,PlE43,54drt,r2344

应分为以下令牌:

  

'abe 123'和'PlE43'和'54drt'和'r2344'

如何修复我的正则表达式以适应条件? (现在我无法使逗号可选,但是如果它在那里我期望另一个有效的令牌,以及使用逗号以及作为有效分隔符之前或之后的任何空格组合)

5 个答案:

答案 0 :(得分:7)

假设您想要折叠所有空格(即,令牌内的两个空格以及令牌/逗号旁边的空格都应该被忽略),您可以通过一些预处理更简单地完成它。

$input = 'abe 123, PlE43,54drt , r2344';
$input = str_replace(' ', '', $input); // strip all spaces
$tokens = explode(',', $input);
foreach ($tokens as $token) {
    if(!preg_match('/^[A-Za-z0-9]{3,6}$/', $token)) {
        // error
    }
}

如果您有两个连续的逗号,或者您使用逗号结束输入字符串,此代码也会报告错误,因为这会在$tokens中生成一个空元素,该元素不会被3-to验证-6字母数字规则。

See it in action

更新:要保留内部标记内的空格,需要稍加修改:

$input = 'abe 123, PlE43,54drt , r2344';
$tokens = explode(',', $input);
foreach ($tokens as &$token) {
    $token = trim($token);
    if(!preg_match('/^[A-Za-z0-9]{3,6}$/', str_replace(' ', '', $token))) {
        // error
    }
}

小心这一点,因为它认为

 a         b                       42

是一个有效的令牌。

答案 1 :(得分:1)

假设要求:

  • 每个令牌由字母,数字和空格组成,但必须至少包含一个字母和至少一个数字。
  • 令牌的总长度为3-6个字符,包括任何内部空格。
  • 假设3-6个字符长度限制包括任何空格。 (因此:“abe 123”,有7个字符,将无效。)
  • 鉴于分隔标记的逗号可能具有可选的空格(可以忽略),暗示标记可能永远不会以空格开头或结尾(但可能包含嵌入的空格)。

这是一个经过测试的PHP函数,它验证给定的字符串并返回包含有效标记的数组。如果字符串无效,则返回false。

// Return array of valid tokens else false if $text is invalid.
function valid_tokens($text) {
    $re_validate = '/
        # Validate comma separated TEXTAREA "Codes" tokens.
        ^                          # Anchor to start of string.
        \s*+                       # Optional leading whitespace.
        (?:                        # Group comma separated tokens.
          (?=[0-9 ]{0,5}[A-Za-z])  # Must contain at least one letter.
          (?=[A-Za-z ]{0,5}[0-9])  # Must contain at least one digit.
          [A-Za-z0-9]              # First char is number or digit.
          [A-Za-z0-9 ]{1,4}        # Middle chars numbers, digits or spaces.
          [A-Za-z0-9]              # Last char is number or digit.
          \s*                      # Optional whitespace following token.
          (?:                      # Group for "end of token" options.
            ,\s*                   # Either a comma, optional whitespace,
          | $                      # or end of string.
          )                        # End "end of token" options group.
        )++                        # One or more tokens required.
        $                          # Anchor to end of string.
        /x';
    // Check validity of comma separated tokens (tokens may contain spaces).
    if (preg_match($re_validate, $text)) {
        $re_match = '/
            # Match next comma separated token. Capture in group $1.
            \s*+                 # Discard optional leading whitespace.
            (                    # $1: Comma separated token.
              [A-Za-z0-9]        # First char is number or digit.
              [A-Za-z0-9 ]{1,4}  # Middle chars numbers, digits or spaces.
              [A-Za-z0-9]        # Last char is number or digit.
            )                    # End $1: Comma separated token.
            \s* ,?               # Discard comma separator if its there.
            /x';
        preg_match_all($re_match, $text, $matches);
        return $matches[1]; // Return array of valid tokens.
    }
    // Case 2: TEXTAREA does not contain valid tokens. Return false.
    else return FALSE;
}

这个脚本使用两个主要的正则表达式;一个用于验证整个逗号分隔的标记字符串,另一个用于提取每个值。

编辑:我对该问题的原始解读使其变得更加复杂。此简化版本仅允许以逗号分隔的标记。

答案 2 :(得分:0)

试试这个:

[A-Za-z0-9]{3,6}((\s*\,\s*)[A-Za-z0-9]{3,6}|(\s)*)

答案 3 :(得分:0)

这个正则表达式可能会起作用。

^([A-Za-z0-9]{3,6} *, *)*[A-Za-z0-9]{3,6}$

首先查找任意数量的令牌,然后是sperator。然后它需要一个令牌。 在这种情况下,逗号之前和之后允许任意数量的空格。你可能想调整一下。

您的示例将不匹配,因为它在第一个标记中包含空格(不带逗号)。如果要传递,则应将空格添加到有效字符标记列表中。

答案 4 :(得分:0)

我会使用以下内容:

/^(?:([A-Za-z0-9\s]{3,6})\s*(?:,\s*|$))*/

这会将每个textarea的内容放入捕获组1.请注意,我已将[A-Za-z0-9]修改为[A-Za-z0-9\s],这将允许abe 123示例中的空格。这也会修剪逗号周围的空格。

请注意,这不会从字符串的开头和结尾修剪空格。为了保持一致性,我建议你修剪它们。这样做的正则表达式是:

/^(?:\s*([A-Za-z0-9\s]{3,6})\s*(?:,|$))*/

还有一次更新:如果你想忽略3-6个字符数的空格,你可以这样做:

/^(?:((?:\s*[A-Za-z0-9]\s*){3,6})(?:,|$))*/

使用您的示例数据进行测试:http://refiddle.com/10t