일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Visual Studio Code
- border-width
- 이미지바꾸기
- Git
- ion-range
- Sentry
- oh-my-zsh
- NVM
- Ionic
- JavaScript
- zsh
- change detection
- typescript
- error
- aab 배포
- rxjs
- hashchange
- angular5
- sealize
- IONIC3
- 자바스크립개념
- angular
- 테두리굵기
- VSCode
- fromEvent
- 변화감지
- code .
- ChangeDetectorRef
- php
- getElementsByClassName
- Today
- Total
hsunny study blog
Glob을 사용해서 원하는 확장자 파일 안에 있는 문자열들을 치환하기 (+@ 정규식) 본문
프로젝트 내에 특정 파일들을을 일정한 규칙이 있는 문자열로 모두 변경해야 할 때가 있다.
이때 스크립트를 작성하여 실행하면 간편한 수정이 가능하다.
누군가에게 도움일 될거라 생각하며! 작업 과정의 일부를 공유한다.
작업을 위한 선행과정으로 before, after를 구분할 수 있는 JSON 파일을 만든다.
나의 경우 before을 path 로, after를 to-be로 이름지었다.
원하는 확장자의 파일만 수정할 수 있도록 'glob' 라이브러리를 사용한다.
glob이 실제 프로젝트에 쓰인다면 package.json에 목적에 맞게 넣으면 되지만, 나의 경우에는 치환 작업만 진행할 것이라 작업을 완료하고 삭제하였다.
npm i glob
내가 변경할 내용을 담은 스크립트를 작성한다.
실행에 필요한 일부 코드들을 공유한다.
함수 구조
const path = require('path');
const fs = require('fs');
const glob = require('glob');
function convertString() {
function explodeFolder() { } // 타겟 폴더 안에 타겟 확장자 파일을 탐색함
function convertTarget() { } // 실제 변경을 진행하는 곳
function generateFileIncludeAffectedFileList() { } // 변경내역을 확인하려는 목적으로 파일을 생성함
}
function getBaseFile() { } // 가장 처음에 만든 JSON 파일을 불러오기 위해 사용
function convertToRegPattern() { } // 밑에서 설명
function addWrapRegPattern() { } // 밑에서 설명
function replacePattern() { // 개인 작업 특이사항을 진행하기 위해 작성
function replacer() { }
}
function modifyFile() { } // 파일을 수정함**
exports.changeString = convertString; // 스크립트 실행을 위해 export
일부 과정을 상세 소개해보자면..
탐색을 시작할 경로를 지정한다.
const rootDir = path.join(__dirname, '../');
지정한 경로를 시작으로 내가 설정한 폴더 안에 있는 파일들을 탐색한다.
fs.readdirSync(rootDir) // 폴더 리스트를 배열 형태로 반환 (동기)
.filter(folder => folder === 'projects' || folder === 'src') // projects, src 폴더만 탐색
.forEach((value) => {
explodeFolder(rootDir + value, version); // 폴더 내에 있는 파일을 모두 탐색
});
explodeFolder() 메소드로 들어온 값을 확인하여, 파일인 경우 원하는 변경 작업을 진행한다.
function explodeFolder(path, version) {
let dirList = fs.readdirSync(path);
for (const file of dirList) {
let pullPath = path + '/' + file;
const isDir = fs.statSync(pullPath).isDirectory();
if (isDir) {
explodeFolder(pullPath, version); // 폴더인 경우 재귀
const fileList = glob.sync(pullPath + '/' + '*.ts'); // typescript 파일들만 배열 형태로 반환
fileList.forEach(file => convertTarget(file, version)); // 문자열 변경 진행
}
}
}
convertTarget() 메소드에서 문자열 변경을 진행하고, 변경사항을 반영한다.
sheetData = getBaseFile(); // 처음에 만들어둔 JSON 파일
...
function convertTarget(pullPath, version) {
let fileContent = fs.readFileSync(pullPath, 'utf-8'); // 파일 내용 반환 (동기)
sheetData = sheetData.reduce((acc, v, i) => {
const regPattern = convertToRegPattern(v.path); // **
const matchList = getMatchedString(fileContent, regPattern); // ** 변경된 파일을 요소로 포함하는 배열을 반환
...
fileContent = replacePattern(fileContent, regPattern, version);
acc.push(v);
return acc;
}, []);
modifyFile(fileContent, pullPath); // fs.writeFileSync(filePath, fileContent);
}
Regular expression()
실제 치환작업을 위해서는 정규식을 사용했고, 작성한 정규식은 아래와 같다.
치환을 할 대상을 선정하고, 자신에게 맞게 정규식을 변경하면 된다!
function convertToRegPattern(path) {
let fullPattern = path;
const regex = /:[a-z]+[_]?[a-z]+/g;
const searchRegex = '("\\s?\\+\\s?|\\$(?=\\{)\\{)[\\w.]+(\\s?\\+\\s?"|})';
fullPattern = fullPattern.replace(regex, searchRegex);
fullPattern = addWrapRegPattern(fullPattern);
return new RegExp(fullPattern, 'g');
}
function addWrapRegPattern(regPattern) {
return `(path:\\s?)?(\'|\"|\`|\})\\s?(${regPattern}[\'\"\`\{\?])`;
}
convertToRegPattern()
찾아야했던 형태
:p_target, :id, ${p.id}, ${target}, " + target + "
- +: 한 번 이상 나올 수 있음을 의미
- \$(?=\{): 무조건 { 앞에 $가 있어야 함을 의미
- \w. : 모든 문자열을 의미 (숫자 제외)
- \: 특수문자의 경우 앞에 \를 붙여 특수문자임을 알려줌
- 정규식에서 사용하는 의미있는 기호($, + 등)를 특수문자 자체로 쓰기 위해서는 꼭 필요
- ?: 앞에 해당하는 정규식은 있어도 되고 없어도 됨을 의미
- \s: 공백문자를 의미
addWrapRegPattern()
return `(path:\s?)?(\'|\"|\`|\})\s?(${regPattern}[\'\"\`\{\?])`;
- ()로 묶은 것: 하나의 그룹으로 취급 (순서대로 $1, $2, $3,,,)
- []: 내부에 있는 문자는 각각 대응
- 여러 케이스에 대응하기 위한 문자열을 넣을 때.. () 안에서는 or(|)이 필요하지만 [] 안에서는 필요 없음
addWrapRegPattern()에서 그룹화된 결과물은 아래와 같은 방식으로 처리하는데 사용했다.
function replacer(match, p1, p2, p3) {
// 'path:'를 포함하는 경우 'path:'가 p1이 되고, 없는 경우 p1은 undefined
if (p1) {
return `${p1}${p2}${p3}`;
} else {
return `${p2}/v1${p3}`;
}
}
나의 경우는 걸프를 사용하고 있어, package.json에 아래와 같이 스크립트를 추가했다.
"scripts": {
...
"change-string": "gulp changeString --gulpfile build-config/gulpfile.js"
}
npm run change-tring
이렇게 작성한 파일을 돌리면 내가 설정한 타겟들이 정규식에 맞추어 수정된다.
참고사이트
정규식을 만드는데 정말 큰 도움이 된 사이트! https://regexr.com/
Tests 활용을 많이 했다.