正则表达式选择与模式不匹配的所有字符

时间:2017-11-15 17:16:01

标签: javascript regex

我对正则表达式很弱但是把以下正则表达式放在一起,选择何时满足我的模式,问题是我需要选择任何不符合模式的字符。

/^\d{1,2}[ ]\d{1,2}[ ]\d{1,2}[ ][AB]/i

正确的模式是:

## ## ## A|B aka [0 < x <= 90]*space*[0 < x <= 90] [0 < x <= 90] [A|B]

EG:

  • 12 34 56 A→good
  • 12 34 56 B→好
  • 12 34 5.6 A→糟糕 - 选择
  • 12 34 5.6 C→错误 - 选择 C
  • 1A 23 45 6→不好 - 选择 A 6

编辑: 我的印象是正则表达式用于同时执行字符和模式/序列的验证。一个简单的问题是如何选择不适合非负数,空格和不同字符类别的字符。

1 个答案:

答案 0 :(得分:2)

答案1

由于正则表达式的性质,1个正则表达式无法真正实现 。这个答案提供了一个正则表达式,可以捕获最后错误条目。对于多个不正确的条目,必须使用循环。您可以通过在生成的捕获组上运行一些代码逻辑来更正不正确的条目,以确定它无效的原因。

我的最终建议是将字符串拆分为已知的分隔符(在本例中为空格字符,然后使用某些逻辑(甚至是小的正则表达式)来确定它的错误原因和如何修复它,如答案2 中所示。

非匹配

以下逻辑适用于我的第二个答案。

对于任何想知道我做了什么来捕捉错误匹配的用户:在最基本的层面上,所有这个正则表达式都在向正则表达式的每个子部分添加|(.*)。某些部分需要对捕获特定的无效字符串格式进行其他更改,但|(.*)或稍作修改可能会解决其他任何问题。

其他修改包括:

  • 使用相反的令牌
    • 例如:匹配一个数字
      • 原始正则表达式:\d
      • 正则表达式\D
    • 例如:匹配数字或空格
      • 原始正则表达式:[\d\s]
      • 相反的正则表达式:[^\d\s]
        • 注意[\D\S] 不正确,因为它匹配两组字符,因此,任何非空格或非数字字符(因为非空格包括数字和非数字包括空格,两者都将匹配)
  • 负面的向前看
    • 例如:一个月内最多可​​以捕捉31天
      • 原始正则表达式\b(?:[0-2]?\d|3[01])\b
      • 正则表达式:\b(?![0-2]?\d\b|3[01]\b)\d+\b

代码

首先,根据OP的问题创建更多正确的正则表达式,同时确保0 < x <= 90

^(?:(?:[0-8]?\d|90) ){3}[AB]$

See regex in use here

^(?:(?:(?:[0-8]?\d|90) |(\S*) ?)){3}(?:[AB]|(.*))$

注意:此正则表达式使用mi标志(多行 - 假设输入采用该格式,并且不区分大小写)

其他格式

实际上,这个后面的正则表达式是理想的。遗憾的是,JavaScript并不支持正则表达式中使用的某些令牌,但我觉得它可能对OP或其他看到此问题的用户有用。

See regex in use here

^(?:(?:(?:[0-8]?\d|90) |(?<n>\S*?) |(?<n>\S*?) ?)){3}(?:(?<n>\S*) )?(?:[AB]|(.*))$

结果

输入

第一部分(由额外换行符/分隔符分隔的部分)显示有效字符串,而第二部分显示无效字符串。

0 45 90 A
0 45 90 B

-1 45 90 A
0 45 91 A
12 34 5.6 A
12 34 56 C
1A 23 45 6
11 1A 12 12 A
12 12  A
12 12 A

输出

0 45 90 A        VALID
0 45 90 B        VALID

-1 45 90 A       INVALID: -1
0 45 91 A        INVALID: 91
12 34 5.6 A      INVALID: 5.6
12 34 56 C       INVALID: C
1A 23 45 6       INVALID: 1A, 6
11 1A 12 12 A    INVALID: 12 A
12 12  A         INVALID: (missing value)
12 12 A          INVALID: A, (missing value)

注意:最后一个条目显示奇数输出,但这是由于JavaScript的正则表达式引擎的限制。 其他格式部分描述了这个以及用于正确捕获这些情况的另一种方法(使用不同的正则表达式引擎)

说明

这使用简单的|(OR)并将不正确的匹配捕获到捕获组中。

  • ^在行首处断言位置
  • (?:(?:(?:[0-8]?\d|90) |(\S*) ?)){3}完全匹配以下3次
    • (?:(?:[0-8]?\d|90) |(.+))匹配以下任一项
      • (?:[0-8]?\d|90)匹配以下任一项,后面跟一个空格字符
        • [0-8]?\d匹配集0-8中的零个字符和其中一个字符(08之间的数字),后跟任意数字
        • 90按字面意思匹配90
      • (\S*) ?将任何非空白字符一次或多次捕获到捕获组1中,然后将零或一个空格字符逐字地
  • (?:[AB]|(.*))匹配以下任一项
    • [AB]匹配集合中的任何字符(AB
    • (.*)任意次数捕获任何字符到捕获组2
  • $断言行尾的位置

答案2

此方法在给定分隔符上拆分字符串,并测试每个部分以获取正确的字符集。如果值不正确,它会输出一条消息。您可能会使用您想要使用的逻辑替换控制台输出。

代码

&#13;
&#13;
var arr = [
  "0 45 90 A",
  "0 45 90 B",
  "-1 45 90 A",
  "0 45 91 A",
  "12 34 5.6 A",
  "12 34 56 C",
  "1A 23 45 6",
  "11 1A 12 12 A",
  "12 12  A",
  "12 12 A"
];

arr.forEach(function(e) {
  var s = e.split(" ");
  var l = s.pop();
  var numElements = 3;
  var maxNum = 90;
  var syntaxErrors = [];
  if(s.length != numElements) {
    syntaxErrors.push(`Invalid number of elements: Number = ${numElements}, Given = ${s.length}`);
  }
  s.forEach(function(v) {
    if(v.match(/\D/)) {
      syntaxErrors.push(`Invalid value "${v}" exists`);
    } else if(!v.length) {
      syntaxErrors.push(`An empty value or double space exists`);
    } else if(Number(v) > maxNum) {
      syntaxErrors.push(`Value greater than ${maxNum} exists: ${v}`);
    }
  });
  if(l.match(/[^AB]/)) {
    syntaxErrors.push(`Last element ${l} in "${e}" is invalid`);
  }
  if(syntaxErrors.length) {
    console.log(`"${e}" [\n\t${syntaxErrors.join('\n\t')}\n]`);
  } else {
    console.log(`No errors found in "${e}"`);
  }
});
&#13;
&#13;
&#13;