如何使用正则表达式捕获指定JavaScript对象名称后的首个多行对象内容
So you're trying to grab the exact object literal assigned to the DirectoryData variable in your Svelte store code, right? Your initial regex was too greedy and either grabbed everything to the end of the file or nothing—totally frustrating, I've been there.
Let's break down why your first attempt didn't work: The pattern (.*|\n|\r|\n\r|\0)* uses greedy matching, which means it will keep consuming characters until it hits the very end of the input. It has no way to stop at the closing }); of your target object, especially since there are other objects later in the file.
The Solution: A Balanced Regex for Nested Braces
Since your object has nested braces (like stateObj: {}), we need a regex that can handle balanced pairs of {} instead of just stopping at the first closing brace. Here's a working pattern tailored to your code:
const regex = /const DirectoryData.*?writable<[^>]+>\((\{(?:[^{}]+|(?R))*\})\);/s;
Let's break down what each part does:
const DirectoryData: Targets the exact variable declaration you care about.*?: Non-greedy match to skip over the type annotation and store setup without jumping past our targetwritable<[^>]+>: Matches thewritablestore call, even if the generic type (like<State>) changes\(: Matches the opening parenthesis of thewritablecall(\{(?:[^{}]+|(?R))*\}): The magic part—this captures a balanced set of braces.(?:[^{}]+|(?R))*means "match either non-brace characters, or recursively match the entire brace group" (handles nested objects)\);: Matches the closing parenthesis and semicolon of the store callsmodifier: Makes the.character match newlines, so the regex works across multiple lines
How to Use It
Here's a full code example to extract the object block you want:
const code = `import { writable } from 'svelte/store'; import type { Writable } from 'svelte/store'; import type { NewFile, EditorCacheType, EditorObj, State } from '../types'; const DirectoryData: Writable<State> = writable<State>({ mainDir: '', fileTree: [], openFilePath: '', fileRead: false, stateObj: {}, activeFile: '', rename: false, deleteFile: false, activeDir: '', createFile: false, createFolder: false, createMainFile: false, createMainFolder: false, reload: false, activeFolder: '', }); const openTabs: Writable<NewFile[]> = writable<NewFile[]>([]); const currentTabFilePath: Writable<string> = writable<string>('');`; const regex = /const DirectoryData.*?writable<[^>]+>\((\{(?:[^{}]+|(?R))*\})\);/s; const match = code.match(regex); if (match) { // Get the object literal (including outer braces) const objectLiteral = match[1]; // Format it into the full block you want const desiredBlock = `(${objectLiteral});`; console.log(desiredBlock); }
Running this will output exactly what you're looking for:
({ mainDir: '', fileTree: [], openFilePath: '', fileRead: false, stateObj: {}, activeFile: '', rename: false, deleteFile: false, activeDir: '', createFile: false, createFolder: false, createMainFile: false, createMainFolder: false, reload: false, activeFolder: '', });
Notes
- The
(?R)recursive pattern works in ES2018+ (all modern browsers and Node.js 10+ support this) - If you don't need to handle nested braces, you could simplify the regex, but this version is robust for real-world JS objects
- The
[^>]+inwritable<[^>]+>ensures we match any generic type, not just<State>
内容的提问来源于stack exchange,提问作者HirsuteJim

