【问题标题】:How can I get the exact latest npm version from a relative version?如何从相对版本中获取确切的最新 npm 版本?
【发布时间】:2020-03-05 11:27:42
【问题描述】:

我希望能够获得与相关语义版本匹配的npm 的最新发布版本。

例如,我想运行类似的东西:

npm -v 6.12.x

然后返回匹配的确切最新版本:

=> 6.12.1

我已经探索了一些可用的文档和命令,或者认为这可以通过 npm 实现,但我没有看到任何不安装另一个全局依赖项的工作。

【问题讨论】:

  • 你说“我希望能够获得最新发布的版本......” - 你是什么意思?你的意思是; 1) 您想获得最新发布的 npm 版本吗? 2) 您想获得其他软件包的最新发布版本吗? 3) 还是别的什么?你的意思是不是类似于npm semver calculator 的工作方式,即semver 包?
  • 我想要最新发布的npm 版本,类似于 semver 计算器的工作方式,但使用的是最新版本。

标签: npm semantic-versioning


【解决方案1】:

简短回答: npm 不提供完全满足您的要求的内置功能。

不过,npm 确实提供了npm-view 命令。它的文档说明如下:

如果提供了版本范围,则将为包的每个匹配版本打印数据。这将显示每个匹配的 yui3 版本需要哪个版本的 jsdom:

npm view yui3@'>0.5.4' dependencies.jsdom.

下面给出的两个解决方案演示了如何解析/操作npm view 命令的输出以满足您的要求(无需安装另一个全局依赖项)。


解决方案 A:*仅适用于 Nix 平台(Linux/MacOS...)

因此,可以借助一些额外的 Bash 实用程序来解析输出,从而实现您的要求。

考虑运行以下复合命令:

npm view npm@'6.12.x' version | tail -n 1 | cut -d "'" -f2

说明

下面对上述复合命令中的组成部分进行说明:

  1. npm view npm@'6.12.x' version

    这部分利用npm view命令返回给定范围内的所有版本,即6.12.x

    独立运行这些部分会将以下内容打印到您的控制台:

    npm@6.12.0 '6.12.0'
    npm@6.12.1 '6.12.1'
    
  2. | tail -n 1

    然后使用-n 1 选项将之前显示的结果通过管道传送到tail,以便只打印最后一行。

    跑步:

    npm view npm@'6.12.x' version | tail -n 1
    

    打印:

    npm@6.12.1 '6.12.1'

  3. | cut -d "'" -f2

    然后使用-d 选项将前面显示的结果通过管道传送到cut,并指定单引号作为分隔符。然后-f2 部分选择第二项。

    运行完整的复合命令:

    npm view npm@'6.12.x' version | tail -n 1 | cut -d "'" -f2
    

    打印您想要的结果:

    6.12.1

Semver 波浪号 (~) 和插入符号 (^) 范围。

您还可以使用上述复合命令指定波浪号或插入符号范围。

示例:

  • 指定波浪号范围:

    npm view npm@'~4.0.0' version | tail -n 1 | cut -d "'" -f2
                  ^^^^^^
    

    打印:

    4.0.5

  • 指定插入符号范围:

    npm view npm@'^4.0.0' version | tail -n 1 | cut -d "'" -f2
                  ^^^^^^
    

    打印:

    4.6.1

简化用法:

如果您打算经常在 *nix 上运行该命令,那么我建议:

  1. 运行以下复合命令:

    echo $'\n'"npmv() { npm view \"npm@\${1}\" version | tail -n 1 | cut -d \"'\" -f2; }" >> ~/.bash_profile
    

    这会将shell function 添加到您的.bash_profile 文件的内容中,即它将添加一个新行,内容为:

    npmv() { npm view "npm@${1}" version | tail -n 1 | cut -d "'" -f2; }

  2. 然后当您创建一个新会话(即创建新窗口或重新启动终端)时,您可以简单地运行:

    npmv 6.12.x
    

    它更简洁,更类似于您问题中给出的示例命令。

注意:如果您已经在系统上全局安装了名为 npmv 的 npm 包,则为 shell 函数/命令选择不同的名称以避免任何冲突。


解决方案 B:跨平台(Windows/Linux/macOS...)

如果您使用的是 Windows,或者想要一个跨平台的解决方案(即在 Windows、Linux 和 macOS 上成功运行的解决方案......),您将需要利用 nodejs 来满足您的要求。

考虑运行以下复合命令:

node -e "var res = require('child_process').execSync('npm view npm@"\"6.12.x\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"

是的,我同意它与 Solution A :)

相比有点冗长

说明

下面对上述复合命令中的组成部分进行说明:

  1. node -e "..."

    我们调用 node 并使用 nodejs 命令行选项 -e 来评估给定的内联 JavaScript。

  2. var res = require('child_process').execSync('npm view npm@"\"6.12.x\"" version', {encoding: 'utf-8'})

    这部分给定的 node.js 脚本 (JavaScript) 使用 execSync(),根据 Solution A 输出相同的 npm view 命令,即 npm view npm@"\"6.12.x\"" version

  3. .split('\n').filter(Boolean);

    npm view 命令的结果使用 String 的 split() 方法从字符串转换为数组 - 本质上,结果的每一行都由换行符 \n 分割,因此每一行输出都变成一个数组中的元素。

    .filter(Boolean) 部分从数组中删除由npm view 命令打印的附加尾随空行产生的空元素。

  4. if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } ... }

    这里我们使用一些条件if..else 语句来确保我们从数组中获得所需的项目。

  5. console.log(res.replace(/[']/g, ''));

    最后,我们将结果记录到控制台并使用replace() 方法删除包含semver 值的单引号(')。

Semver 波浪号 (~) 和插入符号 (^) 范围。

根据Solution A,您还可以使用上述复合命令指定波浪号或插入符号范围。

示例:

  • 指定波浪号范围:

    node -e "var res = require('child_process').execSync('npm view npm@"\"~4.0.0\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"
                                                                          ^^^^^^
    

    打印:

    4.0.5

  • 指定插入符号范围:

    node -e "var res = require('child_process').execSync('npm view npm@"\"^4.0.0\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"
                                                                          ^^^^^^
    

    打印:

    4.6.1

【讨论】:

  • 感谢您回答我的问题 - 鉴于 npm 不提供命令(我在 Linux 上执行此操作),解决方案 1 非常完美。
猜你喜欢
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
  • 2022-01-27
相关资源
最近更新 更多