【问题标题】:Javascript and Regex: Get index of a captured stringJavascript 和正则表达式:获取捕获字符串的索引
【发布时间】:2014-11-14 04:41:23
【问题描述】:

这是我的问题:

  • 我有一个正则表达式,这个表达式包含一个,而且只有一个捕获组,
  • 此正则表达式无法更改,
  • 我有一个字符串,将匹配这个正则表达式,
  • 正则表达式将匹配完整的字符串,它不是查找,如果正则表达式无法与字符串匹配,则函数将在到达此步骤之前失败。

=> 我想获取捕获的子字符串在字符串中的位置,以及它的长度。

示例;

如果我的正则表达式是

^.*?\/F?L?(\d+)$

我的字符串是

"( 413) 250/FL250"

我想得到143

在这些条件下,搜索将返回 1

这是一个简单的例子,但我们可以有非常复杂的正则表达式,但原理总是一样的:一个且只有一个捕获组,并在主组中找到捕获的字符串的位置。

非常感谢您的帮助,我被卡住了。

版本:

所以我用 ant(我们的基本工作环境是 ant)做了一些事情,包括获取捕获组的 leftContext,然后确定它的大小。要获得leftContext,我只需将捕获组的括号移到左侧。例如:\d(\s) 变为 (\d)\s。

所以我有一个问题:

<macrodef name="Get_CaptureGroup_Position" >
    <attribute name="text" />
    <attribute name="mask" />
    <attribute name="start" />
    <attribute name="end" />
    <sequential>

        <var name="_GMLCS_modified_regex"       unset="true"/>
        <var name="_GMLCS_leftContext"          unset="true"/>
        <var name="_GMLCS_leftContext_len"      unset="true"/>
        <var name="_GMLCS_CapturedGroup"        unset="true"/>
        <var name="_GMLCS_CapturedGroup_len"    unset="true"/>

        <propertyregex property="_GMLCS_modified_regex" override="yes"  input="@{mask}" regexp="(.*[^\\])\)([^?].*)" replace="\1\2" />  
        <propertyregex property="_GMLCS_modified_regex" override="yes" input="${_GMLCS_modified_regex}" regexp="(.*[^\\])\(([^?].*)" replace="\1)\2" />
        <var name="_GMLCS_modified_regex" value="(${_GMLCS_modified_regex}" />

        <propertyregex property="_GMLCS_leftContext"    override="yes" input="@{text}" regexp="${_GMLCS_modified_regex}" select="\1" />
        <propertyregex property="_GMLCS_CapturedGroup"  override="yes" input="@{text}" regexp="@{mask}" select="\1" />

        <getAttributeLength text="${_GMLCS_leftContext}"    property="_GMLCS_leftContext_len" />
        <getAttributeLength text="${_GMLCS_CapturedGroup}"  property="_GMLCS_CapturedGroup_len" />

        <math result="_GMLCS_leftContext_len"   operation="+" operand1="${_GMLCS_leftContext_len}" operand2="1" />
        <math result="_GMLCS_CapturedGroup_len" operation="+" operand1="${_GMLCS_leftContext_len}" operand2="${_GMLCS_CapturedGroup_len}" />

        <var name="@{start}" value="${_GMLCS_leftContext_len}" />
        <var name="@{end}" value="${_GMLCS_CapturedGroup_len}" />

        <var name="_GMLCS_modified_regex"       unset="true"/>
        <var name="_GMLCS_leftContext"          unset="true"/>
        <var name="_GMLCS_leftContext_len"      unset="true"/>
        <var name="_GMLCS_CapturedGroup"        unset="true"/>
        <var name="_GMLCS_CapturedGroup_len"    unset="true"/>
    </sequential>
</macrodef>

我的问题是,当我通过这个正则表达式时:

(?:A|.*)/F?L?(\d+)\s*\d*(?:A|.*)

我明白了:

第一个属性正则表达式:

(?:A|.*)/F?L?(\d+\s*\d*(?:A|.*) = CORRECT

第二个属性正则表达式:

(?:A|.*)/F?L?)\d+\s*\d*(?:A|.*) = CORRECT

变量:

((?:A|.*)/F?L?)\d+\s*\d*(?:A|.*) = CORRECT

开始和结束:7 和 10 = 正确。

这实际上是正确的,但我认为不应该,我的问题是为什么(?:...) 块末尾的“)”没有被删除?

【问题讨论】:

    标签: javascript regex string indexing substring


    【解决方案1】:

    这是我们对问题的最终答案。 它是由 ANT 完成的,但我认为它可以转置为 javascript:

    <macrodef name="Get_CaptureGroup_Position" >
    <attribute name="text" />
    <attribute name="mask" />
    <attribute name="start" />
    <attribute name="end" />
    <sequential>
    
        <var name="_GMLCS_modified_regex"       unset="true"/>
        <var name="_GMLCS_leftContext"          unset="true"/>
        <var name="_GMLCS_leftContext_len"      unset="true"/>
        <var name="_GMLCS_CapturedGroup"        unset="true"/>
        <var name="_GMLCS_CapturedGroup_len"    unset="true"/>
    
        <propertyregex property="_GMLCS_modified_regex" override="yes" input="@{mask}" regexp="^((?:|(?:[^\\]|\\.)*))\(([^?].*)$" replace="(\1\2" />
    
        <propertyregex property="_GMLCS_leftContext"    override="yes" input="@{text}" regexp="${_GMLCS_modified_regex}" select="\1" />
        <propertyregex property="_GMLCS_CapturedGroup"  override="yes" input="@{text}" regexp="@{mask}" select="\1" />
    
        <getAttributeLength text="${_GMLCS_leftContext}"    property="_GMLCS_leftContext_len" />
        <getAttributeLength text="${_GMLCS_CapturedGroup}"  property="_GMLCS_CapturedGroup_len" />
    
        <math result="@{start}" operation="-" operand1="${_GMLCS_leftContext_len}" operand2="${_GMLCS_CapturedGroup_len}" datatype="int"/>
        <math result="@{start}" operation="+" operand1="${@{start}}" operand2="1" datatype="int"/>
        <var name="@{end}" value="${_GMLCS_leftContext_len}" />
    
        <var name="_GMLCS_modified_regex"       unset="true"/>
        <var name="_GMLCS_leftContext"          unset="true"/>
        <var name="_GMLCS_leftContext_len"      unset="true"/>
        <var name="_GMLCS_CapturedGroup"        unset="true"/>
        <var name="_GMLCS_CapturedGroup_len"    unset="true"/>
    </sequential>
    

    【讨论】:

      【解决方案2】:

      通过以下两种方法获取长度很简单,但一般情况下不可能获取捕获组捕获的文本的开始和结束索引。 p>

      String.match 的第一种方法,仅适用于非全局 RegExp

      // reNonGlobal can be a variable containing RegExp object
      // or a RegExp object directly specified.
      var result = inputString.match(reNonGlobal);
      
      if (result != null) {
          console.log(result[groupNumber].length);
      }
      

      RegExp.exec 的第二种方法,对于任何RegExp

      var arr;
      // The RegExp object must be assigned to a variable
      var re = ...;
      
      if (re.global) {
          while ((arr = re.exec(inputString)) != null) {
              console.log(arr[groupNumber].length);
      
              // lastIndex is not advanced when empty string is matched
              // Need to manually advance it to prevent infinite loop
              if (arr[0].length == 0) {
                  re.lastIndex += 1;
              }
          }
      } else {
          if ((arr = re.exec(inputString)) != null) {
              console.log(arr[groupNumber].length);
          }
      }
      

      使用indexOf(或任何其他方法)来定位捕获文本的索引不可靠,并且取决于特定的正则表达式和/或输入。

      【讨论】:

      • 我认为的一种可能性是动态修改正则表达式字符串以捕获实际在捕获组之前的所有内容,并确定它的长度。 ^.*?\/F?L?(\d+)$ 会变成: (^.*?\/F?L?)\d+$ 所以我需要在 "(" 字符上拆分正则表达式字符串,但是它不应该在“(?:”而不是“(”)上拆分你有想法做这个拆分吗?谢谢
      • 似乎:[^\\]\([^?] 给出了一些结果。
      • @user3870905:如果你想修改它,你需要解析正则表达式。即便如此,它也无法帮助您获得重复捕获组的正确起始索引。
      • 没问题,我们只有一个捕获组。如果我们有 0 或多于 1,则构建失败。
      • @user3870905:我说的是(a|aaa)* 之类的案例(可能是更大模式的一部分)
      猜你喜欢
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 2012-08-20
      • 2015-10-28
      • 2014-08-27
      • 2016-12-15
      相关资源
      最近更新 更多