Regex for matching JS import statements

Viewed 5766

I'm using node to read a file's contents. I need to match a particular import statement where the file looks something like this.

I need to match only the line or lines containing the "foo-bar" package. I'm interested in getting the imports from that package.

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'
import { foo, bar, fooBar } from 'foo-bar'
import { anotherThing } from 'another-module'

It can also span multiple lines like this.

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'
import { 
    foo, 
    bar, 
    fooBar 
} from 'foo-bar'
import { anotherThing } from 'another-module'

I've tried using this regex but it's matching all lines from "import" to the end of the line containing foo-bar. I only want to match the import to the end of the line or lines that end with "foo-bar". Is this possible using JavaScript regex? Also, if there's a better way other than using regex i'm open to other options as well

import([\s\S]*?)(?=foo-bar').*

Single line example: https://regex101.com/r/U1j2G6/1

Multi-line example: https://regex101.com/r/kcA7gd/1

3 Answers

I developed this regular expression that matches anything that would work as a valid import statement:

import([ \n\t]*(?:[^ \n\t\{\}]+[ \n\t]*,?)?(?:[ \n\t]*\{(?:[ \n\t]*[^ \n\t"'\{\}]+[ \n\t]*,?)+\})?[ \n\t]*)from[ \n\t]*(['"])([^'"\n]+)(?:['"])

It has the following capturing groups:

  • $1 imported variables
  • $2 quotes used for the import
  • $3 import path

For your case, you could test $3.

Be careful using it since it also matches occurrences inside strings. Also, I wouldn't use it blindly, migth have bugs and it is slow.

I used the following file for testing:

import someClass from "src"
import someClass from"src"
import
someClass
from
"src"
import someClass
from       "src"

import {class1,class2} from "src"
import {
    class1,
    class2
            } from"src"

    import {
        class1

                } from "src"

import defaultClass   ,

{
    class1
}

  from "src"

import defaultClass,

{
    class1
}from "src"

import someClass from "src";import someClass from "src"


"I disagree about your import practices from 'src/who knows where'"
`import someClass from "src"
import someClass from"src"
import
someClass
from
"src"
import someClass
from       "src"

import {class1, class2} from "src"
import {
    class1,
    class2
            } from"src"

    import {
        class1

                } from "src"

import defaultClass   ,

{
    class1
}

  from "src"

import defaultClass,

{
    class1
}from "src"
`

I got around the problem you had by using a negative capturing group - which will match as many characters as possible, up to }.

Here's the regex.

import {[^}]*}.*'foo-bar'

Try it online!

Here is an updated and improved version of @Antón Kryukov Chinaev's answer:

import(?:(?:(?:[ \n\t]+([^ *\n\t\{\},]+)[ \n\t]*(?:,|[ \n\t]+))?([ \n\t]*\{(?:[ \n\t]*[^ \n\t"'\{\}]+[ \n\t]*,?)+\})?[ \n\t]*)|[ \n\t]*\*[ \n\t]*as[ \n\t]+([^ \n\t\{\}]+)[ \n\t]+)from[ \n\t]*(?:['"])([^'"\n]+)(['"])

...with support for import * as x from 'y' which it lacked, aswell as improved capture groups and stricter to prevent false matches such as importx from'y'.

The new capture groups are:

  • $1 = default import name (can be non-existent)
  • $2 = destructured exports (can be non-existent)
  • $3 = wildcard import name (can be non-existent)
  • $4 = module identifier
  • $5 = quotes used (either ' or ")

Regex101 Playground with tests used

Related