# rexscan

> scan text with RegExp.

Latest version **1.0.2** (published 2020-08-31) · MIT license · 0 weekly downloads

## Install

```sh
npm install rexscan
pnpm add rexscan
yarn add rexscan
bun add rexscan
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.2 |
| Published | 2020-08-31 |
| First published | 2020-08-30 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 15.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | YEBISUYA Sugoroku |
| Maintainers | sugoroku-y |

## Links

- npm: https://www.npmjs.com/package/rexscan
- npm.io page: https://npm.io/package/rexscan

## Recent versions

- 1.0.2 (latest) — 2020-08-31
- 1.0.1 — 2020-08-31
- 1.0.0 — 2020-08-30

## README

# rexscan

Scanning text for regular expressions.

テキストを正規表現でスキャンします。

[![Build Status](https://travis-ci.org/sugoroku-y/rexscan.svg?branch=master)](https://travis-ci.org/sugoroku-y/rexscan)
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)

```ts
import * as fs from 'fs';
import {scan} from 'rexscan';

(async () => {
  const text = awit fs.promises.readFile('test.txt', 'utf8');
  for (const match of scan(/\w+/g, text)) {
    console.log(match.index, match[0]);
  }
})()
```

いちいち調べるのも面倒なので、以下の情報も`match`からアクセスできるようにしています。

- `prevLastIndex` : 前回の`exec`後の`lastIndex`。1回目のときは0。
- `startIndex` : 今回の`exec`前の`lastIndex`。
- `lastIndex` : 今回`exec`後の`lastIndex`。

また、最後に実行した`exec`後の`index`(ただしループ終了後は`undefined`)、最後に成功した`exec`後の`lastIndex`(こちらはループ終了後も取得可能)も取得できるようにしています。

```ts
  let replacing = '';
  const g = scan(re, target);
  try {
    for (const match of g) {
      replacing += target.slice(match.prevLastIndex, match.index);
      replacing += replaceValue(match)
    }
    // g.lastIndexは最後に成功した`exec`後の`lastIndex`
    replacing += target.slice(g.lastIndex);
  } catch (ex) {
    // 例外の発生した位置を示す
    throw new Error(`${ex.toString()}:
  ${target}
  ${' '.repeat(g.index ?? target.length)}^`);
  }
```

## API

```ts
/**
 * 文字列に正規表現を順次適用させて、マッチしなくなるまで繰り返します。
 *
 * マッチした結果はジェネレーターで順次返していきます。
 *
 * ただし、空文字列にマッチした場合、同じ位置から`exec`すると無限ループになるので、1文字進ませます。
 *
 * 最後に成功した`exec`後の`lastIndex`については、この関数の返値が持つ`lastIndex`プロパティで取得できます。
 * @param re 文字列に適用する正規表現。
 * @param target 正規表現を適用する文字列。
 * @yields {RegExpExecArray & {prevLastIndex: number;startIndex: number;lastIndex: number;}} `exec`に成功したときの結果(RegExpExecArray)。
 *
 * それに追加して、以下のプロパティを持つ。
 * - `prevLastIndex`: 前回のexec後のlastIndex。1回目のときは0。
 * - `startIndex`: 今回のexec前のlastIndex。
 * - `lastIndex`: 今回exec後のlastIndex。
 */
export function scan(
  re: RegExp,
  target: string
): Generator<RegExpMatch, void> & {index: number | undefined; lastIndex: number} {
```

`scan`を使った例として、Stringのメソッド二種を再実装してみました。

いずれもちょっとだけ仕様をかえてあります。

```ts
/**
 * 文字列の置換を行う。
 *
 * ex)
 * ```ts
 * const replaced = replace(/\w+/g, ({0: match, index}) => `${index}: ${match}`);
 * ```
 * @param {string} target 置換対象の文字列。
 * @param {RegExp} re 検索する正規表現。
 * @param {(match: RegExpMatch) => string} replaceValue 置換後の文字列を返す関数。
 * 引数にRegExpExecArrayを受け取り、置換後の文字列をかえす。
 * @returns {string} 置換後の文字列
 */
export function replace(
  target: string,
  re: RegExp,
  replaceValue: (match: RegExpMatch) => string
): string {
```

```ts
/**
 * 文字列を正規表現でマッチするパターンで分割する。
 * @param target 分割対象の文字列。
 * @param re 分割するパターン。
 * @param [limit] 分割数の最大値。ただし、正規表現でキャプチャされた文字列についてはカウントしない。
 * @returns {string[]} 分割結果の配列。
 * 正規表現でキャプチャされた文字列があればそれも含まれる。
 * limitが指定されていれば最大でその個数
 * (ただし、正規表現でキャプチャされた文字列についてはカウントしない)
 * になるように分割する。
 */
export function split(target: string, re: RegExp, limit?: number): string[] {
```

---
_Source: https://npm.io/package/rexscan · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
