美文网首页js css htmllinuxnode
使用 zx 编写在 Node 中编写 Bash 脚本

使用 zx 编写在 Node 中编写 Bash 脚本

作者: lio_zero | 来源:发表于2022-04-26 16:44 被阅读0次

本文已整理到 Github,地址 👉 blog

如果我的内容帮助到了您,欢迎点个 Star 🎉🎉🎉 鼓励鼓励 :) ~~


Bash 是一种命令语言,通常作为命令行解释程序出现,用户可以在其中从他们的终端软件执行命令。例如,我们可以使用 Ubuntu 的终端来运行 Bash 命令。我们还可以通过 shell 脚本创建和运行 Bash 脚本文件。

我们经常在许多自动化场景中使用 shell 脚本,例如构建过程、CI/CD 或与计算机维护相关的活动。作为一种功能齐全的命令语言,Bash 支持管道、变量、函数、控制语句和基本算术运算。

然而,Bash 不是一种通用的开发人员友好型编程语言。它不支持 OOP、JSON 等结构、数组以外的通用数据结构,以及内置的字符串或数组操作方法。这意味着程序员通常需要从 Bash 中调用单独的 Python 或 Node 脚本来满足这些需求。

这就是 zx 项目的用武之地。zx 引入了一种使用 JavaScript 编写类似 Bash 的脚本的方法。

相比之下,JavaScript 几乎具有开发人员所需的所有内置功能。zx 允许我们通过为几个关键的 CLI 相关 Node.js 包提供包装 API(如:child_process),用 JavaScript 编写 shell 脚本。因此,可以使用 zx 编写开发人员友好的、类似 Bash 的 shell 脚本。

本文将介绍 zx 的一些用法,如何在项目中使用它。

zx 是如何工作的?

每个 zx shell 脚本文件都有 .mjs 扩展名。第三方 API 的所有内置函数和包装器都是预先导入的。因此,您不必在基于 JavaScript 的 shell 脚本中使用额外的 import 语句。

zx 接受来自标准输入、文件和 URL 的脚本。它将您的 zx 命令集导入为 ECMAScript 模块(MJS)来执行,命令执行过程使用 Node.js 的 child_process API

安装

全局安装 zx:

$ npm i -g zx

版本要求:node >= 16.0.0

在终端运行 zx 以检查程序是否已成功安装:

$ zx

Usage:
   zx [options] <script>

 Options:
   --quiet            : don't echo commands
   --shell=<path>     : custom shell binary
   --prefix=<command> : prefix all commands
   --experimental     : enable new api proposals
   --version, -v      : print current zx version

你也可以单独在项目引入。

顶层 await

为了在 Node.js 中使用顶级 await,在异步函数之外进行 await,我们需要在 ES 模块中编写代码,它支持顶级 await

我们可以通过在 package.json 中添加 "type": "module" 来表示项目中的所有模块都是 ES 模块,或者我们可以将单个脚本的文件扩展名设置为 .mjs

基本语法

首先,文件扩展使用 .mjs 以便可以在顶层使用 await,如果您还是喜欢原来的 .js,需要包装一个 async 函数。

其次,需要在文件的顶部加上 #!/usr/bin/env zx

以下是获取项目的当前 Git 分支示例:

// demo.mjs
#!/usr/bin/env zx

const branch = await $`git branch --show-current`
console.log(`当前分支:${branch}`)
  • #!/usr/bin/env zx 告诉操作系统的脚本执行器选择正确的解释器。
  • $ 是一个函数,它执行给定的命令,并在与 await 关键字一起使用时返回其输出。

最后,我们使用 console.log 来显示当前分支。

运行脚本,以获取项目的当前 Git 分支:

$ zx demo.mjs

它还将显示您执行的每个命令,因为 zx 在默认情况下打开了详细模式。

通过添加以下内容,即可消除额外的命令详细信息。

$.verbose = false

由于我们在第一行使用了 shebang#!),我们也可以在不使用 zx 命令的情况下运行脚本。

$ chmod +x ./demo.mjs

颜色和格式

zx 暴露了 chalk API。因此,我们可以使用它进行着色和格式化,如下所示。

#!/usr/bin/env zx

$.verbose = false
let branch = 1
chalk.level = 1
console.log(`当前分支:${chalk.red.bold(branch)}`)

查看 chalk 的官方文档以了解更多的着色和格式化方法。

用户输入和命令行参数

zx 提供提问功能,从命令行界面捕获用户输入。您还可以使用选项来启用传统的 Unix 选项卡完成功能。

它使用的是 Node 的 readline 包。

以下脚本将捕获文件名和模板。它使用用户输入的配置构建一个文件。

#!/usr/bin/env zx
$.verbose = false
let filename = await question('文件名是什么? ')
let template = await question('你最喜欢的模板是什么? ', {
  choices: ['function', 'class']
})
let content = ''

if (template == 'function') {
  content = `function main() {
    console.log('Test')
}`
} else if (template == 'class') {
  content = `class Main {
    constructor() {
        console.log('Test')
    }
}`
} else {
  console.error(`无效模板: ${template}`)
  process.exit()
}

fs.outputFileSync(filename, content)

已解析的命令行参数对象可作为全局 argv 常量使用。解析是使用 minimist 模块完成的。

下面的示例捕获了两个命令行参数值。

#!/usr/bin/env zx
$.verbose = false
const size = argv.size
const isFullScreen = argv.fullscreen
console.log(`size=${size}`)
console.log(`fullscreen=${isFullScreen}`)

运行上述脚本文件,以检查命令行参数的支持。

$ zx ./demo .mjs --size=1080 --fullscreen

# size=1080
# fullscreen=true

网络请求

我们经常使用 curl 命令通过 Bash 脚本发出 HTTP 请求。zx 为 node-fetch 模块提供了一个包装器,它将特定模块的 API 公开为 fetch。优点是 zx 不会像 Bash 使用 curl 那样为每个网络请求生成多个进程 ,因为 node-fetch 包使用 Node 的标准 HTTP API 来发送网络请求。

以下使用 zx 发送 HTTP 请求:

#!/usr/bin/env zx

$.verbose = false
let response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
if (response.ok) console.log(await response.text())

/*
{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}
*/

构建命令管道

在 shell 脚本中,管道指的是多个顺序执行的命令。我们经常在 shell 脚本中使用众所周知的管道字符(|),将输出从一个进程传递到另一个进程。zx 提供了两种不同的方法来构建管道。

我们可以将 | 字符与类似于 Bash 脚本的命令集一起使用 ,或者我们也可以使用 zx 内置 API 中的 pipe() 方法。

使用 |

#!/usr/bin/env zx

$.verbose = false
let greeting = await $`echo "hello World" | tr '[h]' [H]`
console.log(`${greeting}`)

使用 pipe()

#!/usr/bin/env zx

$.verbose = false
let greeting = await $`echo "Hello world"`.pipe($`tr '[w]' [W]`)
console.log(`${greeting}`)

高级用法

除了基于 JavaScript 的 shell 脚本支持外,zx 还支持其他一些有用的功能。

默认情况下,zx 使用 Bash 解释器来运行命令。我们可以通过修改 $.shell 来更改默认 shell 配置变量。下面的脚本使用 sh shell 而不是 bash。

$.shell = '/usr/bin/sh'
$.prefix = 'set -e;'

$`echo "Your shell is $0"` // Your shell is /usr/bin/sh

zx 命令行程序也可以从 URL 运行远程脚本。以提供文件名的方式提供 zx 脚本的链接。

以下是 zx 仓库提供的一个示例:

$ zx https://github.com/google/zx/blob/main/examples/interactive.mjs

其他:

  • 与 TypeScript 一起使用
  • GitHub Actions
  • etc

详细内容可以查看官方文档

相关文章

  • 使用 zx 编写在 Node 中编写 Bash 脚本

    本文已整理到 Github,地址 ? blog[https://github.com/lio-zero/blog...

  • 特殊字符

    # 注释符 #!/bin/bash 写在脚本开始的最前面,表示这个脚本需要使用/bin/bash 来解释# ...

  • Bash基础知识

    在上一篇文章《不过时的技术-Bash脚本》中,我们简单介绍了Bash脚本,并且学会如何编写、运行一个Bash脚本。...

  • Postman 脚本编程

    Postman 使用 Javascript 编写测试脚本,它运行在 Node.js 之上,因此也继承了 Node....

  • bash脚本编写

    一,概括: read命令是用于从终端或文件中读取输入的内部命令 读取整行输入 每行末尾的换行符不被读入 二,rea...

  • Shell脚本基础入门

    一、shell脚本介绍 1.1 开头(环境使用shebang机制) #!/bin/bash 必须写在文件首行 符号...

  • shell脚本简单的基本语法

    1.脚本的格式要求 1.脚本以#!/usr/bash开头,表示编写的脚本以bash这种终端解释器来解析。 2.脚本...

  • 入门:脚本

    总结 脚本就是给机器一行一行执行的文本 Bash 脚本有Bash 脚本的语法,Node.js 脚本有 JS 语法 ...

  • bash/node编写简单脚本文件

    在计算机领域,脚本是指计算机按照文本内容执行指令。接下来我会分别以bash和node两种环境分别编写脚本完成新建文...

  • zsh 你不知道那些事儿-002-INTERACTIVE_COM

    在使用 bash 或 zsh 编写脚本的时候,可以使用 # 注释掉一行代码,在交互式的 shellcommand ...

网友评论

    本文标题:使用 zx 编写在 Node 中编写 Bash 脚本

    本文链接:https://www.haomeiwen.com/subject/nyfcdrtx.html