balanced-match 源码解析

news/2024/7/19 15:30:54 标签: js, json, library

balanced-match 源码解析

文章目录

  • balanced-match 源码解析
  • 正文
    • 0. 基本信息
      • 0.1 Usage
      • 0.2 Version: v2.0.0
      • 0.2 Doc
    • 1. 源码解析
      • 1.0 源码项目结构
      • 1.1 主入口
      • 1.2 balanced
      • 1.3 maybeMatch
      • 1.4 range
  • 其他资源
    • 参考连接
    • 阅读笔记参考

正文

0. 基本信息

0.1 Usage

balanced-match 这个库的目标很简单:匹配第一个符合条件的一对字符串,同时将其拆解成前、中、后等三部分

0.2 Version: v2.0.0

这个库相对比较稳定了,也没啥好改的

本篇研究的是目前最新版本:v2.0.0

0.2 Doc

相关文档都写在 READEME 里面,还是比较简明的

传送门:balanced-match - npm

1. 源码解析

1.0 源码项目结构

整个项目非常小,就是一个 index.js

1.1 主入口

  • index.js(阅读笔记:/index.js/0_structure.js
js">'use strict';

function balanced(a, b, str) {}

function maybeMatch(reg, str) {}

balanced.range = range;

function range(a, b, str) {}

module.exports = balanced;

整个项目就三个方法,并向外导出两个方法:balancedbalanced.range

1.2 balanced

接下来来看主入口的细节

  • index.js(阅读笔记:/index.js/1_balanced.js
js">/**
 * @param {string | RegExp} a
 * @param {string | RegExp} b
 * @param {string} str
 */
function balanced(a, b, str) {
  // 适配 regexp 输入
  if (a instanceof RegExp) a = maybeMatch(a, str);
  if (b instanceof RegExp) b = maybeMatch(b, str);

  // 寻找范围
  const r = range(a, b, str);

  // 计算前后结果
  return (
    r && {
      start: r[0],
      end: r[1],
      pre: str.slice(0, r[0]),
      body: str.slice(r[0] + a.length, r[1]),
      post: str.slice(r[1] + b.length),
    }
  );
}

函数同时允许传入字符串与正则表达式,所以先使用 maybeMatch 方法进行适配,然后调用 range 方法取得范围,最后重新从原字符串抽取返回结果

1.3 maybeMatch

  • index.js(阅读笔记:/index.js/2_maybeMatch.js
js">/**
 * @param {RegExp} reg
 * @param {string} str
 */
function maybeMatch(reg, str) {
  // match[0] 为第一个匹配的字符串
  const m = str.match(reg);
  return m ? m[0] : null;
}

作者没有对正则表达式使用过多的奇淫技巧,实际上就是直接去原字符串搜有没有匹配的,然后直接转化回字符串

1.4 range

range 函数可以说是这个库的核心,在于根据 a、b 查找第一个非嵌套对,下面拆分成几个步骤

  • index.js(阅读笔记:/index.js/3_range.js
js">/**
 * @param {string} a
 * @param {string} b
 * @param {string} str
 */
function range(a, b, str) {
  let begs, beg, left, right, result;
  let ai = str.indexOf(a);
  let bi = str.indexOf(b, ai + 1);
  let i = ai;

  // 至少存在一对结果
  if (ai >= 0 && bi > 0) {
    // 是否相等
    if (a === b) {
      return [ai, bi];
    }
    begs = [];
    left = str.length;

一开始先确保至少存在一对,同时如果匹配到同一个下标就直接返回(前后之间不可能存在任何其他嵌套对了)

js">    while (i >= 0 && !result) {
      // 搜集所有匹配 a 的下标
      if (i === ai) {
        begs.push(i);
        ai = str.indexOf(a, i + 1);
      } else if (begs.length === 1) {
        // 只剩下一个 begs 时输出结果
        result = [begs.pop(), bi];
      } else {
        beg = begs.pop();
        if (beg < left) {
          // 每弹出一个 a,记录最后一对结果下标
          left = beg;
          right = bi;
        }

        bi = str.indexOf(b, i + 1);
      }

      i = ai < bi && ai >= 0 ? ai : bi;
    }

接下来是循环过程,首先收集所有符合 a 的字符串;然后一步步弹出 a 来与下一个 b 匹配,最后返回第一个符合条件的 a、b 对

js">    // 对于 begs 没用完的情况(a 出现次数 > b)
    if (begs.length) {
      result = [left, right];
    }
  }

  return result;
}

对于 a 出现次数比 b 多的时候,则根据前面记录的 left、right 来找到最后一个符合条件的 a、b 对(也就是最外层的第一对字符串)

其他资源

参考连接

TitleLink
balanced-match - npmhttps://www.npmjs.com/package/balanced-match
balanced-match - Githubhttps://github.com/juliangruber/balanced-match
String.prototype.indexOf() - MDNhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf

阅读笔记参考

https://github.com/superfreeeee/Blog-code/tree/main/source_code_research/balanced-match-2.0.0


http://www.niftyadmin.cn/n/735131.html

相关文章

只允许在同一个月内选择,并且不能超过当天日期

2019独角兽企业重金招聘Python工程师标准>>> var timeobj {};timeobj.max ; // 用于记录&#xff0c;结束框&#xff0c;最大值timeobj.min ; // 用于记录&#xff0c;结束框&#xff0c;最小值timeobj.stime ; //用于记录开始的时间timeobj.etime ;//开…

brace-expansion 源码解析

brace-expansion 源码解析 文章目录brace-expansion 源码解析正文0. 基本信息1. 源码解析1.0 代码结构1.1 主入口 expandTop1.2 转译/反转译 escapeBraces、unescapeBraces1.3 递归展开 expand1.3.1 不存在 {}1.3.2 忽略 ${}1.3.3 展开 {}1.3.4 非序列 > 保留原字符串1.3.5 …

安卓GridView奇偶行不同颜色

背景&#xff1a;安卓制作表格&#xff0c;两列多行&#xff0c;奇数行和偶数行背景色不同 分析&#xff1a;GridView是经常用来制作表格的&#xff0c;但是和ListView不同&#xff0c;不能简单的用position % 2 0/1 来判断奇偶行&#xff0c;下面提供一个方案来解决问题 // a…

minimatch 源码解析

minimatch 源码解析 文章目录minimatch 源码解析正文0. 基本信息1. 源码解析1.1 项目展开1.2 Minimatch1.2.1 构造函数1.2.2 make 初始化表达式解析1.2.3 裁剪前导 !1.2.4 花括号展开1.2.5 分段 & parse 正则表达式转换1.2.6 正则表达式转换&#xff1a;第一部分 - 初始化状…

hadoop大数据研发平台

一&#xff0e;开发平台&#xff1a;•Hadoop是Apache软件基金会旗下的一个开源分布式计算平台•以分布式文件系统&#xff08;Hadoop Distributed File Syste, HDFS&#xff09;和MapReduce为核心的Hadoop为用户提供了系统底层细节透明分布式基础架构•HDFS的高容错、高伸缩的…

wrappy 源码解析

wrappy 源码解析 文章目录wrappy 源码解析正文0. 基本信息1. 源码解析2. 作者实现其他资源参考连接阅读笔记参考正文 0. 基本信息 version&#xff1a;v1.0.2功能&#xff1a;实现函数科里化包装 1. 源码解析 整个项目很小&#xff0c;就一个方法 wrappy.js&#xff08;阅…

python.day.01——运算符分类

运算符分类&#xff1a;算数运算符、赋值运算符、比较运算符、逻辑运算符、成员运算符 一、算数运算符 运算符描述实例(a3,b2)加运算&#xff1a;两数相加a b 5-减运算&#xff1a;两数相减 a - b 1 *乘运算&#xff1a;两个数相乘a * b 6/除运算&#xff1a;两数相除&…

once 源码解析

once 源码解析 文章目录once 源码解析正文0. 基本信息1. 源码解析1.1 源码结构1.2 once 基本款1.3 onceStrict 严格模式1.4 原型方法其他资源参考连接阅读笔记参考正文 0. 基本信息 version&#xff1a;v1.0.4功能&#xff1a;返回只执行一次的函数的高阶函数 吐槽&#xff…