New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

regex-each

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

regex-each

Iterate matches in a string using a JavaScript regular expression

latest
Source
npmnpm
Version
2.0.1
Version published
Maintainers
1
Created
Source

regex-each

Iterate matches in a string using a JavaScript regular expression

Written in typescript targeting ES2015 JavaScript.

Installation

npm install regex-each

Usage

JavaScript:

const { regexEach } = require('regex-each')

Typescript:

import { regexEach } from 'regex-each'

Example

import { regexEach } from 'regex-each'

const words: string[] = []
const nums: number[] = []

// Parse words and numbers.
regexEach(/([a-z]+)|([0-9]+)/i, '10 apples for 5 dollars', (match) => {
  const [, word, num] = match

  if (word != null) {
    words.push(word)
  }

  if (num != null) {
    nums.push(parseInt(num, 10))
  }
})

console.log('nums:', nums)
console.log('words:', words)

Output:

nums: [ 10, 5 ]
words: [ 'apples', 'for', 'dollars' ]

Signature

regexEach(
  expr: RegExp|string,
  str: string,
  onMatch: (match: RegExpExecArray, regex: RegExp) => void
) => void

expr: a regular expression or a string.

  • If expr is a regular expression, it remains unmodified -- an internal copy is made by regex-each. If no sticky or global flag is set on expr, the global flag is added automatically.
  • If expr is a string, it is converted to a regular expression and the global flag is added automatically. There is no way to add other flags when a string is used. If you need flags, create and pass a RegExp object.

str: the string to iterate matches on.

onMatch: called for each match. The match parameter is the regular expression exec result, and the regex parameter is the regular expression used for matching.

RegExp.prototype.each

While monkey-patching globals isn't recommended, it's possible to add regex-each functionality to the RegExp prototype:

import { regexEach, MatchCbk } from 'regex-each'

declare global {
  interface RegExp {
    each(str: string, onMatch: MatchCbk): void
  }
}

RegExp.prototype.each = function (str: string, onMatch: MatchCbk) {
  return regexEach(this, str, onMatch)
}

const re = /([a-z]+)|([0-9]+)/i

re.each('10 apples for 5 dollars', (match) => {
  const [, word, num] = match
  console.log(word, num)
})

Output:

undefined '10'
apples undefined
for undefined
undefined '5'
dollars undefined

More Examples

Parse command-line arguments

import { regexEach } from 'regex-each'

// Define tokens used by the parser.
const tChar = String.raw`[a-z-]`
const tArg = String.raw`--${tChar}+|-${tChar}+`
const tVal = String.raw`\S+`

// Create the parser.
const tParser = String.raw`\s+|(${tArg})|(${tVal})`
const parser = new RegExp(tParser, 'yi')

interface IArgument {
  name: string
  values: string[]
}

/**
 * Parse an argument string.
 */
function parse(str: string) {
  let context: IArgument = { name: '$default', values: [] }
  const args: IArgument[] = [context]

  regexEach(parser, str, (match) => {
    const [_, arg, value] = match

    // Handle arguments, e.g., --something or -s.
    if (arg != null) {
      const name = arg.replace(/-+/, '')
      context = { name, values: [] }
      args.push(context)
    }

    // Handle values.
    if (value != null) {
      context.values.push(value)
    }
  })

  return args
}

const args = parse('each --nums 1 2 3 --alpha abc def g')
console.log(args)

Output:

[
  { name: '$default', values: [ 'each' ] },
  { name: 'nums', values: [ '1', '2', '3' ] },
  { name: 'alpha', values: [ 'abc', 'def', 'g' ] }
]

Parse configuration files

import { regexEach } from 'regex-each'

const configuration =
`
read=true
float
fly

[options]
size=5
root=./data
haltOnError=false

[fruits]
apples
cherries
raspberries
`

interface IContext {
  name: string
  keyVals: {[key: string]: any}
  values: string[]
}

// Define tokens used by the parser.
const tContext = String.raw`\[(.+?)\]`
const tKeyVal = String.raw`(.+?=.*)`
const tVal = String.raw`(\S+)`

// Create the parser.
const tParser = String.raw`${tContext}|${tKeyVal}|${tVal}`
const parser = new RegExp(tParser, 'g')

/**
 * Create and return a context object.
 */
function createContext(name: string): IContext {
  return { name, keyVals: {}, values: [] }
}

/**
 * Parse a configuration file.
 */
function parse(cfg: string) {
  // Create the initial, global-scope context.
  let context = createContext('$global')

  // Store all contexts created during parsing.
  const contextList = [context]

  // Run the parser on the configuration.
  regexEach(parser, cfg, (match) => {
    const [, ctx, keyval, val] = match

    // If a context name is encountered, create a new one.
    if (ctx != null) {
      context = createContext(ctx.trim())
      contextList.push(context)
    }

    // If a key/value pair is encountered, add to context keyVals.
    if (keyval != null) {
      const [key, value] = keyval.split('=')
      try {
        /**
         * Try to parse values as json, e.g., 'true', 'null', '5'.
         * This also allows values to be embeded json, such as
         * '[10, 15, 5, 0, 100]' or '{"items": 5, "category": "parts"}'.
         */
        context.keyVals[key.trim()] = JSON.parse(value.trim())
      } catch (e) {
        context.keyVals[key.trim()] = value.trim()
      }
    }

    // If a regular value is encountered, add to context values.
    if (val != null) {
      context.values.push(val.trim())
    }
  })

  return contextList
}

const items = parse(configuration)
console.log(items)

Output:

[
  {
    name: '$global',
    keyVals: { read: true },
    values: [ 'float', 'fly' ]
  },
  {
    name: 'options',
    keyVals: { size: 5, root: './data', haltOnError: false },
    values: []
  },
  {
    name: 'fruits',
    keyVals: {},
    values: [ 'apples', 'cherries', 'raspberries' ]
  }
]

Keywords

iterate

FAQs

Package last updated on 06 Jun 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts