首页 > 解决方案 > 用正则表达式分解字符串

问题描述

我有一些需要处理的示例字符串

string1 = "_Wondrous item, common (requires attunement by a wizard or cleric)_"
string2 = "_Weapon (glaive), rare (requires attunement)_"
string3 = "_Wondrous item, common_"

我想把它们分解成以下

group1 = {
  type: "Wonderous item"; 
  rarity: "common";
  attune: True
  class: "wizard or cleric"
  }
group2 = {
  type: "Weapon (glaive)";
  rarity: "rare";
  attune : True
  }
group3 = {
  type: "Wondrous item"
  rarity: "common"
  attune: False
  }

我目前拥有的正则表达式很混乱,可能效率低下,但它只会破坏第一个。

regex = /_(?<type>[^:]*),\s(?<rarity>[^:]*)\s\((?<attune>[^:]+)by a(?<class>[^:]*)\)_/U

添加详细信息

标签: javascriptregexmarkdown

解决方案


要使用您的模式获取 3 行的所有组:

_(?<type>[^:]*?),\s+(?<rarity>[^:]*?)(?:\s+\((?<attune>[^:]+?)\s*(?:by\s+a\s+(?<class>[^:]*?))?\))?_
  • _(?<type>[^:]*?)匹配_,组类型:匹配除非贪婪之外的任何字符
  • ,\s匹配,和一个空格字符
  • (?<rarity>[^:]*?)rarity匹配除非:贪婪之外的任何字符
  • (?:非捕获组
    • \s\(匹配一个空白字符和(
    • (?<attune>[^:]+?)\s*:匹配除非贪婪之外的任何字符
    • (?:by a\s+(?<class>[^:]*?))?可选地匹配by a 和分组匹配除非贪婪之外的任何字符的:
    • \)匹配)
  • )?_使外部组可选并匹配_

查看正则表达式演示

如果支持,则使用该groups属性,您可以检查值并相应地更新对象。

const regex = /_(?<type>[^:]*?),\s+(?<rarity>[^:]*?)(?:\s+\((?<attune>[^:]+?)\s*(?:by\s+a\s+(?<class>[^:]*?))?\))?_/;
[
  "_Wondrous item, common (requires attunement by a wizard or cleric)_",
  "_Weapon (glaive), rare (requires attunement)_",
  "_Wondrous item, common_"

].forEach(s => {
  const m = s.match(regex);
  if (m) {
    if (m.groups.class === undefined) {
      delete m.groups.class;
    }
    m.groups.attune = m.groups.attune === undefined ? false : true;
    console.log(m.groups)
  }
});

请注意,在您的模式中,您希望防止:在否定字符类中匹配,但:示例数据中没有。

对于第一个否定字符类,您可以将其更改为不匹配逗号,而对于其他排除匹配括号以获得相同的结果。

这样,并非所有量词都必须是非贪婪的,它可以防止一些不必要的回溯。

_(?<type>[^,]*),\s(?<rarity>[^:()]*)(?:\s\((?<attune>[^()]+?)\s*(?:by a\s+(?<class>[^()]*))?\))?_

查看另一个正则表达式演示


推荐阅读