如何高效使用xonsh脚本编写、迁移与调优?

摘要:xonsh 是 python 驱动的 shell, 在操作效率, 交互和外部功能的先进性上比 bash 等优秀, 并且十分容易上手. 但相应地, 它是一个新兴的 shell, 并且不是所谓 "POSIX Shell
xonsh 是 python 驱动的 shell, 在操作效率, 交互和外部功能的先进性上比 bash 等优秀, 并且十分容易上手. 但相应地, 它是一个新兴的 shell, 并且不是所谓 "POSIX Shell"(尽管某些行为比较相似), 加上现有中文相关文章属实不深, 故自己做了一些较深的了解, 在此处记录心得, 若有错误请您指出, 不胜感谢. xonsh 的提示符为 @, 因为它读作 "consh", 脚本文件扩展名为 .xsh, 官方定义的 markdown 代码块标签也是 xsh 截至本文最后更新, xonsh 的最高版本是 0.22.8 关于 xonsh 的安装和基本自定义, 本文不作赘述, 您可以阅读 Linux 中国等发布的新闻稿或者直接阅读 xonsh 官方安装教程, 安装并使用 xonfig web 等工具 特殊语法 Shell 与 Python 的集成是 xonsh 易用性的根源, xonsh 向下直接兼容多数 python 脚本语法, 并且有提供独特语法以便将 python 和 shell 集成 命令解释与机制相关 引用和处理字符串变量 在 xonsh 中, 你可以直接使用 print(x) 输出一个变量和对象, 但若想将它作为 touch 命令的参数呢? xonsh 能带你告别 bash 丑陋的字符串拼接和 for 语法. xonsh 使用 @() 操作符在 shell 环境中引用一个变量, 它会自动对字符串对象进行 str() 而不是 repr() 操作(也即直接追加字符串), 可以通过下列代码验证: (注意, 对于其他类型 @() 还有其他优雅的行为, 详见下文) tmp @ text = "Hello\nWorld" tmp @ repr(text) "'Hello\\nWorld'" tmp @ str(text) 'Hello\nWorld' tmp @ touch @(text) tmp @ ls 'Hello'$'\n''World' # 文件名中真的有换行 tmp @ # 如果是 repr(), 就会创建 'Hello\nWorld' (无转义) 因此你可以这样创建一组数字序号文件 tmp @ for i in range(30): touch @(i) tmp @ ls 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 tmp @ 或者方便地补0 tmp @ for i in range(30): touch @(str(i).zfill(2)) tmp @ ls 00 02 04 06 08 10 12 14 16 18 20 22 24 26 28 01 03 05 07 09 11 13 15 17 19 21 23 25 27 29 同样的简单操作若用 bash 进行, 需要: for i in {0..29}; do touch $(printf "%02d" $i); done 或 # 避免命令替换的子 shell 开销 for i in {0..29}; do printf -v name "%02d" "$i" touch "$name" done python 还有 bash 无法提供的一系列支持库与工具, 可处理多种格式文件而无需引用外部程序; 并且处理含有奇葩字符的文件名, xonsh 可以使用字符串的 repr 集成到命令中很难炸掉 不过, 同样的操作若用纯 python 脚本/REPL进行, 需要: from pathlib import Path for i in range(0, 30): name = str(i).zfill(2) path = Path(name) path.touch() 这两种对比足以显示 xonsh 的优越性 别名与 aliases 在 xonsh 中, 别名被存储在全局的 aliases -- 一个兼容字典 API 的 xonsh.aliases.Aliases 对象中. 像这样设置一个别名: ~ @ aliases['la'] = 'ls -a' 字符串形式建立的别名将自动转换为列表, 也即对象的智能性: ~ @ aliases['la'] = 'ls -a' ~ @ aliases['la'] ['ls', '-a'] 若要取消一个别名, 只需: ~
阅读全文