根据第一个字符或先前出现的字符限制部分模式

时间:2018-06-03 15:47:50

标签: javascript regex

我有以下正则表达式:

/^(?:(?:>|<)?[a-zA-Z]+(?:(?:\+|-)\d*\.?\d*(?:em)?)?)(?:<[a-zA-Z]+(?:(?:\+|-)\d*\.?\d*(?:em)?)?)?$/

您可以这样考虑:

^
  (?:
    (?:>|<)?
    [a-zA-Z]+
    (?:(?:\+|-)\d*\.?\d*(?:em)?)?
  )
  (?:
    <
    [a-zA-Z]+
    (?:(?:\+|-)\d*\.?\d*(?:em)?)?
  )?
$

实际上,相同的模式重复一次或两次,但差别很小。每个模式的核心是一个或多个字母[a-zA-Z],后跟可选的减号或加号以及可能后跟em的数值。第一个实例可以以<>开头,第二个实例只能以<开头。

所以以下内容都是有效的:

  `alpha`,
  `alphaBravo`,
  `alphaBravoCharlie`,
  `>alpha`,
  `<alpha`,
  `>alpha+10`,
  `<alpha+10`,
  `>alpha+1.5`,
  `<alpha+1.5`,
  `>alpha-10`,
  `>alpha-10`,
  `>alpha-1.5`,
  `>alpha-1.5`,
  `>alpha+10em`,
  `<alpha+10em`,
  `>alpha+1.5em`,
  `<alpha+1.5em`,
  `>alpha-1.5em`,
  `>alpha-1.5em`,
  `alpha-50em<delta-100em`,
  `alpha-50em<delta+100em`,
  `>alpha-50em<delta+100em`,

我的问题是,如果第一个实例以<开头,则不应允许第二个实例,因此以下内容应无效:

<alpha<bravo

是否可以将此限制添加到正则表达式?

我能想到的两种方法是:

  1. 检查第一个字符,如果是<
  2. ,则使第二个实例无效
  3. 检查字符串中是否已<(或者如果字符串中再次出现<),如果是,则使第二个实例无效。
  4. 但是我不确定如何在这里实施这两种方法。

2 个答案:

答案 0 :(得分:3)

您可以在插入符号^之后使用非常早期的否定前瞻:

(?!<[^<\s]*<)

Live demo

您也不需要一次使用替换来匹配单个字符,即(?:>|<)应为[<>](?:\+|-)应为[+-]

扩展模式:

^
  (?!<[^<\s]*<) # We have this extra one
  (?:
    [<>]?
    [a-zA-Z]+
    (?:[-+]\d+(?:\.\d+)?(?:em)?)?
  )
  (?:
    <
    [a-zA-Z]+
    (?:[-+]\d+(?:\.\d+)?(?:em)?)?
  )?
$

排成一行:

^(?!<[^<\s]*<)(?:[<>]?[a-zA-Z]+(?:[-+]\d+(?:\.\d+)?(?:em)?)?)(?:<[a-zA-Z]+(?:[-+]\d+(?:\.\d+)?(?:em)?)?)?$

答案 1 :(得分:2)

只需将(?:(?:>|<)?替换为(?:(?:>|<(?!.*<))?即可获得所需的结果。

测试 here

如果您想将此功能从<字符扩展到>字符,则可以将(?:(?:>|<)?模式的相同部分替换为(?:([<>])(?!.*\1))?并替换{{ 1}}在模式的第二部分中带有<?

测试 here