【问题标题】:How to extract only numbers from string except substring with special character in beginning of numbers如何从字符串中仅提取数字,除了数字开头具有特殊字符的子字符串
【发布时间】:2020-06-07 16:38:20
【问题描述】:

我的计划是从字符串中提取数字,除了带有特殊字符的数字。我的意思是说? 请想象以下情况(如 Excel 公式):

=$A12+A$345+A6789

我需要提取开头不存在任何字符 $ 的数字,因此正确的正则表达式的结果应该是:

12
6789

我在使用以下正则表达式的地方进行了一些调查:

/[A-Z][0-9]+(?![/W])/g

其中提取:

A12
A6789

我正在考虑使用嵌套正则表达式(另外从该结果中提取数字),但我不知道是否可能。到目前为止我的 javascript 源代码:

http://jsfiddle.net/janzitniak/fvczu7a0/7/

问候

一月

【问题讨论】:

    标签: javascript regex data-extraction


    【解决方案1】:
    const regex = /(?<ref>\$?[A-Z]+(?<!\$)[0-9]+)/g;
    const str = `=$A12+A$345+A6789`;
    
    const refs = [...(str.matchAll(regex) || [])].map(result => result.groups.ref);
    
    console.log(refs)
    

    匹配任何包含 A-Z 一次或多次且前面有一个 $ 零或一次,后跟一次或多次但没有前面有 $ 的 A-Z 的字符串。

    您忽略所有匹配的组,但捕获您想要的组,引用为ref(您可以随意调用它)。

    输出:

    ["$A12","A6789"]
    

    如果你只想要数字部分,你可以使用:

    const regex = /\$?[A-Z]+(?<!\$)(?<num>[0-9]+)/g;
    const str = `=$A12+A$345+A6789`;
    const nums = [...(str.matchAll(regex) || [])].map(result => +result.groups.num);
    console.log(nums)
    

    输出:

    [12, 6789]
    

    【讨论】:

    • 通过您的方法,我了解了命名组;我没有意识到这一点,并且仍在计算我的正则表达式中的组捕获括号。谢谢,点赞。
    • @ibraheem 你能再帮我一次吗?如果我想获得以下结果 ["$A13","A6790"],如何增加 ref 输出?
    【解决方案2】:

    const charSequence = '=$A12+A$345+A6789';
    
    const numberList = (charSequence
      .split(/\$\d+/)       // - split at "'$' followed by one or more numbers".
      .join('')             // - join array of split results into string again.
      .match(/\d+/g) || []) // - match any number-sequence or fall back to empty array.
      .map(str => +str);    // - typecast string into number.
    //.map(str => parseInt(str, 10)); // parse string into integer.
    
    console.log('numberList : ', numberList);
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    @ibraheem 你能再帮我一次吗?如果我想获得以下结果 ["$A13","A6790"],如何增加 ref 输出? - JanZitniak 23 分钟前

    ...split/join/match 方法可以非常快速地迭代,因此证明它非常灵活。

    const charSequence = '=$A13+A$345+A6790';
    
    const numberList = (charSequence
      .split(/\$\d+/)       // - split at "'$' followed by one or more numbers".
      .join('')             // - join array of split results into string again.
      .match(/\$*[A-Z]\d+/g) || []);  // - match any sequence of an optional '$' followed
                                      //   by 1 basic latin uppercase character followed
                                      //   by one or more number character(s).
    
    console.log('numberList : ', numberList);
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    Peter 感谢您对增量的快速响应,但在开始时我有 const charSequence = '=$A12+A$345+A6789';作为输出,我需要 ["$A13","A6790"]。 – 扬齐特尼亚克

    ...好的,终于可以全面了解整个问题...这是(1)摆脱不必要的模式...(2)在特定模式中匹配数字并以某种方式记住后者(3)增加这些数字并以某种方式将它们重新加工成它们的记忆/可调用模式

    const anchorSequence = '=$A12+A$345+A6789';
    
    const listOfIncrementedAnchorCoordinates = [...(anchorSequence
    
      // - split at "'$' followed by one or more numbers".
      .split(/\$\d+/)
    
      // - join array of split results into string again.
      .join('')
    
      // - match any sequence of an optional '$' followed by 1 basic latin 
      //   uppercase character followed by one or more number character(s)
      //   and store each capture into a named group.
      .matchAll(/(?<anchor>\$*[A-Z])(?<integer>\d+)/g) || [])
    
      // map each regexp result from a list of RegExpStringIterator entries.
    ].map(({ groups }) => `${ groups.anchor }${ (+groups.integer + 1) }`);
    
    console.log('listOfIncrementedAnchorCoordinates : ', listOfIncrementedAnchorCoordinates);
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    彼得,如果您对另一个问题感兴趣(...ed),我有一个。如何更改 const anchorSequence = '=$A12+A$345+A6789';到以下输出 ["B$345","B6789"]?我的意思是如果字母不以 $ 开头,则按字母顺序将字母更改为下一个(如果是 A,则更改为 B,如果是 B,则更改为 C,依此类推)。在我的示例中,它应该只更改 A$345 和 A6789。 – 扬齐特尼亚克

    ...稍加思考,将之前的版本迭代/重构到最后一个版本并不难...

    const anchorSequence = '=$A12+A$345+A6789';
    
    const listOfIncrementedColumns = [...(anchorSequence
    
      // - split at "'$' followed by 1 basic latin uppercase character 
      //   followed by one or more number character(s)".
      .split(/\$[A-Z]\d+/)
    
      // - join array of split results into string again.
      .join('')
    
      // - match any sequence of 1 basic latin uppercase character
      //   followed by an optional '$' followed by one or more number
      //   character(s) and store each capture into a named group.
      .matchAll(/(?<column>[A-Z])(?<anchor>\$*)(?<row>\d+)/g) || [])
    
      // map each regexp result from a list of RegExpStringIterator entries.
    ].map(({ groups }) => [
    
      // - be aware that "Z" (charCode:90) will be followed by "[" (charCode:91)
      // - thus, the handling of this edge case still needs to be implemented.
      String.fromCharCode(groups.column.charCodeAt(0) + 1),
      groups.anchor,
      groups.row
    
    ].join(''));
    
    console.log('listOfIncrementedColumns : ', listOfIncrementedColumns);
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    【讨论】:

    • @JanZitniak ... 我们开始... split/join/match 方法可以非常快速地迭代。
    • Peter 感谢您对增量的快速响应,但一开始我有 const charSequence = '=$A12+A$345+A6789';作为输出,我需要 ["$A13","A6790"]。
    • 好的,终于要全面了解整个问题了...这是(1)摆脱不必要的模式...(2)匹配特定模式中的数字并以某种方式记住后者(3)增加这些数字并以某种方式将它们重新加工成它们的记忆/可调用模式
    • Peter Seliger 我想告诉你非常感谢你愿意解决我的整个问题!它按我的预期工作。
    • 彼得,如果你对另一个问题感兴趣,我有一个。如何更改 const anchorSequence = '=$A12+A$345+A6789';到以下输出 ["B$345","B6789"]?我的意思是如果字母不以 $ 开头,则按字母顺序将字母更改为下一个(如果是 A,则更改为 B,如果是 B,则更改为 C,依此类推)。在我的示例中,它应该只更改 A$345 和 A6789。
    猜你喜欢
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 2019-12-02
    • 2015-01-28
    • 2011-11-13
    • 1970-01-01
    • 2020-08-26
    相关资源
    最近更新 更多