谷歌 zx 脚手架模块中文文档

简介: 谷歌 zx 脚手架模块中文文档

谷歌 zx 脚手架模块中文文档

#!/usr/bin/env zx
await $`cat package.json | grep name`
let branch = await $`git branch --show-current`
await $`dep deploy --branch=${branch}`
await Promise.all([
  $`sleep 1; echo 1`,
  $`sleep 2; echo 2`,
  $`sleep 3; echo 3`,
])
let name = 'foo bar'
await $`mkdir /tmp/${name}`

Bash 很棒,但是在编写脚本时,人们通常会选择更方便的编程语言。

JavaScript 是一个完美的选择,但是标准Node.js库在使用之前需要额外的麻烦。zx包围绕child_process提供了有用的包装器,对参数进行转义并给出合理的默认值。

安装

npm i -g zx

要求: Node 版本 >= 16.0.0

文档

在扩展名为.mjs的文件中编写脚本,以便能够在顶层使用await。如果您喜欢使用. js扩展名,可以将您的脚本包装成类似于void async function () {...}()

将以下声明添加到您的 zx 脚本的开头:

#!/usr/bin/env zx

现在,您将能够像这样运行您的脚本:

chmod +x ./script.mjs
./script.mjs

或者通过 zx 可执行文件:

zx ./script.mjs

所有函数($cdfetch等)都可以直接使用,无需任何导入。

或者显式导入全局变量(为了在VS代码中更好地自动完成)。

import 'zx/globals'

$`command`

使用child_process包中的 spawn函数执行给定字符串,并返回ProcessPromise<ProcessOutput>

一切都通过 ${...} 将被自动转义并引用。

let name = 'foo & bar'
await $`mkdir ${name}`

不需要额外添加引号。quotes 中阅读更多相关信息

如果需要,您可以传递一组参数:

let flags = [
  '--oneline',
  '--decorate',
  '--color',
]
await $`git log ${flags}`

如果执行的程序返回非零退出代码,将抛出 ProcessOutput

try {
  await $`exit 1`
} catch (p) {
  console.log(`Exit code: ${p.exitCode}`)
  console.log(`Error: ${p.stderr}`)
}
ProcessPromise
class ProcessPromise<T> extends Promise<T> {
  readonly stdin: Writable
  readonly stdout: Readable
  readonly stderr: Readable
  readonly exitCode: Promise<number>
  pipe(dest): ProcessPromise<T>
  kill(signal = 'SIGTERM'): Promise<void>
}

pipe() 方法可用于重定向stdout:

await $`cat file.txt`.pipe(process.stdout)

阅读更多关于 pipelines的信息。

ProcessOutput
class ProcessOutput {
  readonly stdout: string
  readonly stderr: string
  readonly exitCode: number
  readonly signal: 'SIGTERM' | 'SIGKILL' | ...
  toString(): string
}

函数

cd()

更改当前工作目录。

cd('/tmp')
await $`pwd` // outputs /tmp
fetch()

node-fetch 包的包装。

let resp = await fetch('https://wttr.in')
if (resp.ok) {
  console.log(await resp.text())
}
question()

readline 包的包装器。

用法:

let bear = await question('What kind of bear is best? ')
let token = await question('Choose env variable: ', {
  choices: Object.keys(process.env)
})

在第二个参数中,可以指定制表符自动完成的选项数组。

function question(query?: string, options?: QuestionOptions): Promise<string>
type QuestionOptions = { choices: string[] }
sleep()

setTimeout函数的包装。

await sleep(1000)
nothrow()

$ 的行为更改为不在非零退出代码上引发异常。

function nothrow<P>(p: P): P

用法:

await nothrow($`grep something from-file`)
// 一个 pipe() 内部:
await $`find ./examples -type f -print0`
  .pipe(nothrow($`xargs -0 grep something`))
  .pipe($`wc -l`)

如果只需要exitCode,可以使用下一个代码:

if (await $`[[ -d path ]]`.exitCode == 0) {
  ...
}
// 相当于:
if ((await nothrow($`[[ -d path ]]`)).exitCode == 0) {
  ...
}
quiet()

更改 的行为以禁用详细输出。

function quiet<P>(p: P): P

用法:

await quiet($`grep something from-file`)
// 不会显示命令和输出。

以下软件包无需导入内部脚本即可使用。

chalk

chalk 包。

console.log(chalk.blue('Hello world!'))
yaml

yaml 包。

console.log(YAML.parse('foo: bar').foo)
fs

fs-extra 包。

let content = await fs.readFile('./package.json')
globby

globby

let packages = await globby(['package.json', 'packages/*/package.json'])
let pictures = globby.globbySync('content/*.(jpg|png)')

此外,globby可通过 glob 快捷方式获得:

await $`svgo ${await glob('*.svg')}`
os

os

await $`cd ${os.homedir()} && mkdir example`
path

path 包。

await $`mkdir ${path.join(basedir, 'output')}`
minimist

minimist 包。

作为全局常量 argv 提供。

配置

$.shell

指定使用什么 shell 。默认为 which bash

$.shell = '/usr/bin/bash'

或者使用一个 CLI 参数: --shell=/bin/bash

$.prefix

指定将作为所有运行命令的前缀的命令。

默认为: set -euo pipefail;.

或者使用一个 CLI 参数:--prefix='set -e;'

$.quote

指定在命令替换期间转义特殊字符的函数。

$.verbose

指定详细程度。

默认值为 true.

在详细模式下, zx打印所有执行的命令及其输出。

或者使用一个 CLI 参数:--quiet 来设置 $.verbose = false.

Polyfills

__filename & __dirname

ESM 模块中,Node.js不提供 __filename__dirname 全局变量。因为这样的全局变量在脚本中非常方便,所以 zx 提供了这些用于 .mjs 文件中(当使用 zx 可执行文件时)。

require()

ESM 模块中, require() 函数没有被定义。

zx 提供require() 函数,因此它可以与 .mjs 文件中的导入一起使用(当使用 zx 可执行文件时)。

let {version} = require('./package.json')

实验性的

zx还提供了一些实验功能。请在讨论中留下关于这些功能的反馈。

retry()

重试命令几次。将在第一次成功尝试后返回,或将在指定的尝试次数后引发。

import {retry} from 'zx/experimental'
let {stdout} = await retry(5)`curl localhost`
echo()

可以接受 ProcessOutputconsole.log()替代项。

import {echo} from 'zx/experimental'
let branch = await $`git branch --show-current`
echo`Current branch is ${branch}.`
// 或者
echo('Current branch is', branch)
startSpinner()

启动一个简单的CLI微调器,并返回 stop() 函数。

import {startSpinner} from 'zx/experimental'
let stop = startSpinner()
await $`long-running command`
stop()

FAQ

传递环境变量
process.env.FOO = 'bar'
await $`echo $FOO`
传递值数组

如果值的数组作为参数传递给 $,数组的项将被单独转义并通过空格连接。

例如:

let files = [...]
await $`tar cz ${files}`
从其他脚本导入

通过显式导入可以使用 $和其他函数:

#!/usr/bin/env node
import {$} from 'zx'
await $`date`
没有扩展名的脚本

如果脚本没有文件扩展名 (例如 .git/hooks/pre-commit), zx 将假定它是一个 ESM 模块。

Markdown 脚本

zx 可以执行用 markdown 编写的脚本。

zx docs/markdown.md
TypeScript 脚本
import {$} from 'zx'
// Or 
import 'zx/globals'
void async function () {
  await $`ls -la`
}()

使用 ts-node 作为一个 esm node loader.

node --loader ts-node/esm script.ts

你必须i在 package.json 中设置 "type": "module" 以及在 tsconfig.json 中设置"module": "ESNext"

{
  "type": "module"
}
{
  "compilerOptions": {
    "module": "ESNext"
  }
}
执行远程脚本

如果 zx 可执行文件的参数以 https:// 开头,则文件将被下载并执行。

zx https://medv.io/example-script.mjs
zx https://medv.io/game-of-life.mjs
从stdin执行脚本

zx支持从stdin执行脚本。

zx <<'EOF'
await $`pwd`
EOF

License

Apache-2.0

免责声明: 这不是官方支持的谷歌产品。


Quotes(引号)


将参数传递给 ${...} 不需要加引号。如果需要,将自动添加。

let name = 'foo & bar'
await $`mkdir ${name}`

对于引号,zx 使用特殊的bash语法(接下来的命令是有效的bash):

mkdir $'foo & bar'
$'ls' $'-la'

如果添加引号 "${name}",将会产生错误的命令。

如果你需要添加额外的东西,考虑把它放在花括号里。

await $`mkdir ${'path/to-dir/' + name}`

这也将正常工作:

await $`mkdir path/to-dir/${name}`

参数数组

zx 也可以在 ${...} 中接受数组或参数。数组中的项将被单独引用,并通过空格连接起来。

不要添加 .join(' ')

let flags = [
  '--oneline',
  '--decorate',
  '--color',
]
await $`git log ${flags}`

如果你已经有了一个带有数组的字符串,那么正确解析它并区分不同的参数就是你的责任了。比如像这样:

await $`git log ${'--oneline --decorate --color'.split(' ')}`

globbing 和 ~

当一切都通过${...} 将被转义,不能使用 ~glob 语法。

为了实现这个目的,zx提供了 globby package.

而不能这样:

let files = '~/dev/**/*.md' // 错
await $`ls ${files}`

使用 glob 函数和 os”包:

let files = await glob(os.homedir() + '/dev/**/*.md')
await $`ls ${files}`

管道(Pipelines)


zx 支持 Node.js 流(stream),特殊的 pipe() 方法可用于重定向标准输出。

await $`echo "Hello, stdout!"`
  .pipe(fs.createWriteStream('/tmp/output.txt'))
await $`cat /tmp/output.txt`

$ 创建的进程从 process.stdin 获取stdin,但是我们也可以写入子进程:

let p = $`read var; echo "$var";`
p.stdin.write('Hello, stdin!\n')
let {stdout} = await p

管道可用于显示程序的实时输出:

$.verbose = false
await $`echo 1; sleep 1; echo 2; sleep 1; echo 3;`
  .pipe(process.stdout)

通过管道传输stdout和stderr:

let echo = $`echo stdout; echo stderr 1>&2`
echo.stdout.pipe(process.stdout)
echo.stderr.pipe(process.stdout)
await echo

此外,pipe() 方法可以组合 $ 程序。与bash中的 | 相同:

let greeting = await $`printf "hello"`
  .pipe($`awk '{printf $1", world!"}'`)
  .pipe($`tr '[a-z]' '[A-Z]'`)
console.log(greeting.stdout)

使用pipe()nothrow():

await $`find ./examples -type f -print0`
  .pipe(nothrow($`xargs -0 grep ${'missing' + 'part'}`))
  .pipe($`wc -l`)

Markdown 脚本


使用markdown编写脚本是可能的。zx只执行代码块。

您可以运行这个markdown 文件:

zx docs/markdown.md
await $`whoami`
await $`echo ${__dirname}`

__filename 将指向 markdown.md:

console.log(chalk.yellowBright(__filename))

我们也可以在这里使用导入:

await import('chalk')

bash代码(带有 bashsh语言标签)也将被执行:

VAR=$(date)
echo "$VAR" | wc -c

其他代码块被忽略:

body .hero {
    margin: 42px;
}
目录
相关文章
|
人工智能 缓存 开发工具
结合企业实践来规范你的Git commit(含插件使用指南)
结合企业实践来规范你的Git commit(含插件使用指南)
结合企业实践来规范你的Git commit(含插件使用指南)
|
Java
百度搜索:蓝易云【hutool Http 工具发送POST请求的几种方式。】
以上是使用Hutool发送POST请求的几种方式。根据实际需求和代码复杂度,选择合适的方式来发送POST请求。
1123 0
|
人工智能 Cloud Native 大数据
现代后端技术发展趋势与应用前景
随着信息技术的快速发展,现代后端技术在不断演进和创新。本文将探讨现代后端技术的发展趋势和应用前景,并深入分析其中的关键技术和未来发展方向。从云原生、大数据、微服务架构到人工智能等多个方面展开讨论,展示了后端技术在不断推动数字化转型和业务创新中的重要作用。
|
9月前
|
人工智能 自然语言处理 物联网
Jina Embeddings V4: 为搜索而生,多模态多语言向量模型
近日,Jina AI 正式发布 jina-embeddings-v4,一款全新的多模态向量模型,参数规模达到 38 亿,并首次实现了对文本与图像的同步处理。
1230 2
|
Web App开发 安全 中间件
谷歌、火狐、Edge等浏览器如何使用ActiveX控件
allWebPlugin 是一款为用户提供安全、可靠且便捷的浏览器插件服务的中间件产品,支持 Chrome、Firefox、Edge 和 360 等浏览器。其 V2.0.0.20 版本支持一个页面加载多个插件,并解决了插件与浏览器之间的焦点问题。用户可通过“信息化系统 + allWebPlugin + 插件 + 浏览器”的解决方案实现 ActiveX 插件的无缝集成。下载地址见文末,安装包含详细说明。
4519 119
|
SQL 关系型数据库 MySQL
MySQL-在线处理大表数据 & 在线修改大表的表结构
MySQL-在线处理大表数据 & 在线修改大表的表结构
682 0
|
编译器 API C++
【Matlab】解决使用Mex 报错There was a problem creating the mex file for Real Time Execution ,Please ensure y
解决Matlab使用Mex时出现的"Real Time Execution"错误的步骤,即通过安装"MATLAB 支持 MinGW-w64 C/C++ 编译器"这个包来确保编译器设置正确。
384 0
|
SQL jenkins 持续交付
一篇文章掌握 FTP 和本地文件系统的桥梁 - CurlFtpFS
一篇文章掌握 FTP 和本地文件系统的桥梁 - CurlFtpFS
|
机器学习/深度学习 自然语言处理 数据可视化
基于Python大数据的京东产品评论的情感分析的研究,包括snwonlp情感分析和LDA主题分析
本文探讨了基于Python大数据技术对京东产品评论进行情感分析的研究,涵盖了文本预处理、情感分类、主题建模等步骤,并运用了snwonlp情感分析和LDA主题分析方法,旨在帮助电商企业和消费者做出更明智的决策。
813 1
基于Python大数据的京东产品评论的情感分析的研究,包括snwonlp情感分析和LDA主题分析
|
Linux 编译器 C语言
CentOS 快速安装Python3和pip3
CentOS是经常使用的Linux系统之一,特别是作为服务器使用,其只自带了Python2,但是现在使用更广泛的是Python3,因此需要自行安装,同时为了更方便地安装第三方库,还需要安装pip3。