william_0353 2022-09-29 03:38 采纳率: 50%
浏览 208
已结题

正则+js提取包含嵌套括号内容

需要用正则和js匹配一段内容,该内容是产品配料表,包括名称,括号内备注,和含量百分比。需要提取出每一种配料和百分比。
注意:

  1. 目标语言全部是英文,大小写混用
  2. 百分比可能是英文逗号做小数点:33,4% 或者33.4% 都有可能
  3. 括号里面内容要保留,括号可能出现在百分比前或者后。括号内可能有嵌套
  4. 方括号内容都不要
    例子:
    Water 52.64%, sand 13.36% [1], glass12%, concret (-4°-0° brix) 6% [2], grand sand 4.6%, fine added sand (powder, smoke) 0.1%, Sodium sulfate (sodium, calcium, iron (ion), modified glue(FAX)) 4.5%, alkaline sulfides 0.65% (sodium 45%, carbon 0.2%, heptahydrate sodium 0.1%, black stone 0.1%), sulfate ion 0.35%, Potassium sulfate 0.3%, POTAssium chloride 0.3%.

需要得到如下结果:
[ Water 52.64%,
sand 13.36%,
glass12%,
concret (-4°-0° brix) 6%,
grand sand 4.6%,
fine added sand (powder, smoke) 0.1%,
Sodium sulfate (sodium, calcium, iron (ion), modified glue(FAX)) 4.5%,
alkaline sulfides 0.65% (sodium 45%, carbon 0.2%, heptahydrate sodium 0.1%, black stone 0.1%),
sulfate ion 0.35%,
Potassium sulfate 0.3%,
POTAssium chloride 0.3% ]

  • 写回答

5条回答 默认 最新

  • MAXLZ 2022-09-29 12:03
    关注

    js的正则不支持balancing group,所以很匹配出嵌套括号的最外层括号,由于正则本身就是状态机实现,所以这里使用状态机的思路完成配料表的提取。
    https://www.regular-expressions.info/refrecurse.html
    时间复杂度:O(n)
    空间复杂度:O(1),不考虑返回值

    function getChargeMixture(str) {
      const ans = []
      let cur = ''
      // lBrackets:左括号数量
      // hasPercentSymbol:是否存在%,只有左括号数量为0时,该值才为true
      // lRectBrackets:左方括号数量
      let lBrackets = 0, hasPercentSymbol = false, lRectBrackets = 0
      for (const ch of str) {
        // 不拼接[xxx]
        if (ch === '[') {
          lRectBrackets++
          continue
        } else if (ch === ']') {
          lRectBrackets--
          continue
        }
        if (lRectBrackets > 0) continue
        if (ch === ',') {
          // 当字符为,并且左括号为0,存在%时,说明获得一种配料,将其加入结果中
          if (lBrackets === 0 && hasPercentSymbol) {
            ans.push(cur.trim())
            cur = ''
            lBrackets  = 0
            hasPercentSymbol = false
            continue
          }
        } else if (ch === '(') {
          lBrackets++
        } else if (ch === ')') {
          lBrackets--
        } else if (ch === '%') {
          // 只要hasPercentSymbol为true了,之后就不会再发生变化
          if (!hasPercentSymbol) hasPercentSymbol = lBrackets === 0
        }
        cur += ch
      }
      cur && ans.push(cur.trim().replace(/\.$/, ''))
      return ans
    }
    
    const str = `Water 52.64%, sand 13,36% [1], glass12%, concret (-4°-0° brix) 6% [2], grand sand 4.6%, fine added sand (powder, smoke) 0.1%, Sodium sulfate (sodium, calcium, iron (ion), modified glue(FAX)) 4.5%, alkaline sulfides 0.65% (sodium 45%, carbon 0.2%, heptahydrate sodium 0.1%, black stone 0.1%), sulfate ion 0.35%, Potassium sulfate 0.3%, POTAssium chloride 0.3%.`
    
    console.log(getChargeMixture(str))
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
    1人已打赏
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 10月7日
  • 已采纳回答 9月29日
  • 创建了问题 9月29日

悬赏问题

  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分
  • ¥15 Macbookpro 连接热点正常上网,连接不了Wi-Fi。
  • ¥15 delphi webbrowser组件网页下拉菜单自动选择问题
  • ¥15 linux驱动,linux应用,多线程