【问题标题】:How to resolve a path that includes an environment variable, in nodejs?如何在nodejs中解析包含环境变量的路径?
【发布时间】:2014-02-17 06:59:19
【问题描述】:

我想运行一个可执行文件并且它的路径包含一个环境变量,例如如果我想运行 chrome.exe 我想写这样的东西

var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: '%LOCALAPPDATA%\\Google\\Chrome\\Application', env: process.env})

而不是

var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: 'C:\\Users\myuser\\AppData\\Local\\Google\\Chrome\\Application', env: process.env}).

有没有我可以使用的包来实现这一点?

【问题讨论】:

    标签: javascript node.js environment-variables


    【解决方案1】:

    这些答案很疯狂。就可以用path:

    const folder = require('path').join(
        process.env.LOCALAPPDATA,
        'Google/Chrome/Application',
    );
    
    console.log(folder); // C:\Users\MyName\AppData\Local\Google\Chrome\Application
    

    【讨论】:

      【解决方案2】:

      我意识到问题是询问 Windows 环境变量,但我修改了@Denys Séguret 的答案以处理 bash 的 ${MY_VAR}$MY_VAR 样式格式,因为我认为这可能对其他来到这里的人有用。

      注意:这两个参数是因为有两个基于格式变化的分组。

      str.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b])
      

      【讨论】:

      • 我希望我能给你一个赏金,为我节省了大量的时间!
      【解决方案3】:

      这是一个通用的辅助函数:

      /**
       * Replaces all environment variables with their actual value.
       * Keeps intact non-environment variables using '%'
       * @param  {string} filePath The input file path with percents
       * @return {string}          The resolved file path
       */
      function resolveWindowsEnvironmentVariables (filePath) {
        if (!filePath || typeof(filePath) !== 'string') {
          return '';
        }
      
        /**
         * @param  {string} withPercents    '%USERNAME%'
         * @param  {string} withoutPercents 'USERNAME'
         * @return {string}
         */
        function replaceEnvironmentVariable (withPercents, withoutPercents) {
          let found = process.env[withoutPercents];
          // 'C:\Users\%USERNAME%\Desktop\%asdf%' => 'C:\Users\bob\Desktop\%asdf%'
          return found || withPercents;
        }
      
        // 'C:\Users\%USERNAME%\Desktop\%PROCESSOR_ARCHITECTURE%' => 'C:\Users\bob\Desktop\AMD64'
        filePath = filePath.replace(/%([^%]+)%/g, replaceEnvironmentVariable);
      
        return filePath;
      }
      
      • 可以从任何地方调用
      • 首先进行基本类型检查,您可能希望更改第一个 if 块中默认返回的内容
      • 函数的命名方式可以解释它们的作用
      • 变量的命名方式可以解释它们是什么
      • 添加的评论清楚地表明了可能发生的结果
      • 处理用百分比包裹的非环境变量,因为 Windows 文件系统允许将文件夹命名为 %asdf%
      • JSDoc 块用于在某些编辑器中进行自动文档、类型检查和自动完成
      • 您也可以根据需要使用if (process.platform !== 'win32') {}

      【讨论】:

      • +1 以获得可读性和解释性。比 Denys Séguret 的答案更易于维护。相比之下,(感知的)增加的复杂性完全可以忽略不计。人们应该更喜欢这种方式,而不是在你写完之后没有任何意义的单行代码。
      【解决方案4】:

      在 Denys Séguret 的出色答案中添加对 TypeScript 友好的补充:

      let replaced = str.replace(/%([^%]+)%/g, (original, matched) => {
            const r = Process.env[matched]
            return r ? r : ''
      })
      

      【讨论】:

        【解决方案5】:

        您可以使用正则表达式将变量替换为process.env 的相关属性:

        let str = '%LOCALAPPDATA%\\Google\\Chrome\\Application'
        let replaced = str.replace(/%([^%]+)%/g, (_,n) => process.env[n])
        

        如果是单线,我认为不需要包装。

        【讨论】:

        • 好的,我可以用这个,我只是觉得有一些内置的工具。
        • 我知道它简短而直截了当。但这会导致人们盲目地复制粘贴解决方案,这些解决方案只在当下有意义,之后会困扰所有人。请参阅 Jaredcheeda 的文章,了解以后更容易理解的内容。
        【解决方案6】:

        在 Linux/MacOS 上,我生成了一个进程来使用 env 变量解析路径,这是安全的 - 让 bash 为您完成这项工作。显然性能较差,但更健壮。看起来像这样:

        import * as cp from 'child_process';
        
        // mapPaths takes an array of paths/strings with env vars, and expands each one
        
        export const mapPaths = (searchRoots: Array<string>, cb: Function) => {
        
          const mappedRoots = searchRoots.map(function (v) {
            return `echo "${v}"`;
          });
        
          const k = cp.spawn('bash');
        
          k.stdin.end(mappedRoots.join(';'));
          const results: Array<string> = [];
          k.stderr.pipe(process.stderr);
        
          k.stdout.on('data', (d: string) => {
            results.push(d);
          });
        
          k.once('error',  (e) => {
            log.error(e.stack || e);
            cb(e);
          });
        
          k.once('exit', code => {
        
            const pths = results.map((d) => {
              return String(d || '').trim();
            })
            .filter(Boolean);
        
            cb(code, pths);
        
          });
        };
        

        【讨论】:

        • 你能详细说明它是如何更健壮的吗?
        • 我想他的意思是它很健壮,它会以与 bash 完全相同的方式扩展事物(因为它是 bash 这样做,但是,它在另一种方式上不太健壮,因为您的应用程序现在依赖于bash 的存在。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-10
        • 2015-06-20
        • 1970-01-01
        • 2013-09-16
        • 2013-07-26
        • 2010-12-26
        相关资源
        最近更新 更多