
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
Iterate matches in a string using a JavaScript regular expression
Written in typescript targeting ES2015 JavaScript.
npm install regex-each
JavaScript:
const { regexEach } = require('regex-each')
Typescript:
import { regexEach } from 'regex-each'
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' ]
regexEach(
expr: RegExp|string,
str: string,
onMatch: (match: RegExpExecArray, regex: RegExp) => void
) => void
expr: a regular expression or a string.
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.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.
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
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' ] }
]
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' ]
}
]
FAQs
Iterate matches in a string using a JavaScript regular expression
We found that regex-each demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.