Linux shell script 是我最喜欢的脚本之一,历史悠久,底蕴深厚,shell script 几乎是内核的一部分,托 POSIX 标准的福,你可以在任何 Linux 系统中使用它。但是编写 shell script 体验并不太好,各种奇怪的语法、没有类型检查、孱弱的数组支持,有时候排查很久的问题,仅仅是错误的使用引号、或者多了一个空格。
我很喜欢造轮子,曾打算写一个高级语言,可以编译成 shell script 执行,即使是一些简单的语法糖,也能很大程度提升 shell script 用户的幸福感。前几天发现一个项目 Amber 已经做了这些工作,试用了下还不错,语法类似 Ecmas 或者 js,支持 Text、Num、Bool、Null 和 [] 数组,可以直接编译成 shell script,直接拿到任何 shell 中执行,没有任何移植性困扰。
先睹为快
参考官网的安装指导,只需要一行命令:
curl -s "https://raw.githubusercontent.com/Ph0enixKM/AmberNative/master/setup/install.sh" | bash
请确保你的系统已安装了 curl、bc, 安装以后就可以使用 amber
命令。 下面是一个简单的例子:
let fruits = ["apple", "banana", "grape"]
fun show_opt(fruits) {
loop index, f in fruits {
echo "{index}: {f}"
}
}
show_opt(fruits)
将上面的代码保存为 test1.ab
, 执行它
~/test $ amber test1.ab
0: apple
1: banana
2: grape
只要你有任何一种变成经验,很容易明白 amber 的基本语法。
上面的 amber 脚本等效的 shell 如何呢?我们可以将 amber 脚本编译为 shell 脚本。
amber test1.ab test1.sh
相比直接执行 amber 脚本,只需要增加一个参数指定编译输出的脚本文件名即可。test1.sh
看起来这样:
__AMBER_ARRAY_0=("apple" "banana" "grape");
__0_fruits=("${__AMBER_ARRAY_0[@]}");
function show_opt__0_v0 {
local fruits=("${!1}")
index=0;
for f in "${fruits[@]}"
do
echo "${index}: ${f}"
let index=${index}+1
done
};
show_opt__0_v0 __0_fruits[@];
__AMBER_FUN_show_opt0_v0__9=${__AMBER_FUN_show_opt0_v0};
echo ${__AMBER_FUN_show_opt0_v0__9} > /dev/null 2>&1
相比之下,amber 脚本真的是相当人性化。
执行命令
shell 最强大的能力在于可以方便的调用已安装的命令。amber 也具备这样的能力,而且提供了良好的异常处理能力。
基本语法是
$your cmd$ failed { exception handler }
两个 $ 之间可以是任何有效的 shell 命令,failed 是 amber 的关键字,表示指令的异常处理。
为了正常使用异常机制,异常所在代码要么位于 main block,要么在函数中。amber 可以指定 main 作为脚本入口。
main {
let file_name = "1.txt"
let cmd = "cat"
let file_content = ${cmd} {file_name}$ failed {
echo "{file_name} not exist"
fail
}
echo file_content
echo "done"
}
这段代码的尝试获取 1.txt
的内容,如果这个文件不存在就报错退出,否则打印文件内容。
指令可以是任何字符串,比如例子中的命令由 cmd
和 file_name
变量拼接生成。 的标准输出可以直接赋值给变量,获取指令输出非常方便。当使用 调用指令时,必须指定异常处理,可以通过 failed
关键字指明之后的代码块用作异常处理。fail
关键字用于抛出异常。
还有一种简化的一场处理方式,上面代码可以稍作调整:
let file_content = ${cmd} {file_name}$?
相当于
let file_content = ${cmd} {file_name}$ failed {
fail status
}
我很喜欢 ?
的设计,表示指令是不可靠的,出错时就停止。二者的区别是简写方式无法指定报错信息。
总结
目前我已用 amber 作为 Linux 下编写脚本的首选工具,感觉好用。好工具,好生活,拯救脱发。