Javascript file path format extraction

輸入一組路徑,轉換成 sprintf  format

如把

'D:\\\\workspace\\path-parser\\img\\img_0005.txt'

轉換為

D:\\\\workspace\\path-parser\\img\\img_%04d.txt

基本上就是個掃目錄的蠢方法,反正成功了…演算法如下,後面附上 Javascript code

  1. 把輸入路徑轉換成 regex (這邊假定是索引最後一組數字字串)
  2. 在對應目錄下用 regex 找符合的檔名,紀錄最長和最短檔名長度
  3. 如果長度相同,就是有 zero padding ( e.g. %04d ),反之沒有
  4. 根據有沒有 zero padding 決定 format 要怎寫

const fs = require('fs');

let path = 'D:\\\\workspace\\path-parser\\img\\img_0005.txt'
let format = getFormat( path );
console.log( format ); // D:\\\\workspace\\path-parser\\img\\img_%04d.txt


function getFormat( path ) {
    // read dir to find min & max length of path of matched item
    let len = findLength( path );
    // split path
    let match = parsePath( path );

    let format;
    if ( len.max == len.min ) { // has zero padding
        let digitLen = match[2].match(/\d+(?![\s\S]*\d+)/g)[0].length;
        let fileNameRegex = replaceIdx(match[2], `%0${digitLen}d`);
        let dir = match[1].replace(/\\/g, '\\\\');
        format = dir + fileNameRegex + '.' + match[3];
    } else {
        let fileNameRegex = replaceIdx(match[2], '%d');
        let dir = match[1].replace(/\\/g, '\\\\');
        format = dir + fileNameRegex + '.' + match[3];
    }
    
    return format;
    
    ///////////////////////////////////////////////////////////////
    ////////////////////private functions//////////////////////////
    ///////////////////////////////////////////////////////////////
    function parsePath( path ) {
        let reg  = /(.*(?:\\|\/)+)?(.*)\.([^?\s]*)/g
        return reg.exec(path);
    }

    function replaceIdx( fileNameWithoutExt, replaceStr ) {
        // return last match with replaced string
        return fileNameWithoutExt.replace(/\d+(?![\s\S]*\d+)/g, replaceStr);
    }

    function pathToRegexStr( path ) {
        let match = parsePath( path );
        let fileNameRegex = replaceIdx(match[2], '\\d+');
        let dir = match[1].replace(/\\/g, '\\\\');
        let finalPattern = dir + fileNameRegex + '.' + match[3];
        return finalPattern;
    }

    function findLength( path ) {
        let regexPattern = pathToRegexStr( path );
        
        let pathArr = parsePath( path );
        let fileList = fs.readdirSync( pathArr[1] );
        let minLength = 999999;
        let maxLength = 0;
        let minLengthFilePath = '';
        let maxLengthFilePath = '';
        
        let reg = new RegExp(regexPattern);

        // scan all file
        for (let i = 0; i < fileList.length; ++i) {
            let fullPath = pathArr[1]+fileList[i];
            //console.log( 'test: ' + fullPath );
            // find match pattern
            if ( reg.test( fullPath ) ) {
                // update longest path
                if ( fullPath.length > maxLength ) {
                    maxLength = fullPath.length;
                    maxLengthFilePath = fullPath;
                }
                // update shortest path
                if ( fullPath.length < minLength ) {
                    minLength = fullPath.length;
                    minLengthFilePath = fullPath;
                }
            }
        }
        
        return {min: minLength, max: maxLength};
    }
}

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *