马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
xonsh 是 python 驱动的 shell, 在操纵服从, 交互和外部功能的先辈性上比 bash 等精良, 而且非常轻易上手. 但相应地, 它是一个新兴的 shell, 而且不是所谓 " OSIX Shell"(只管某些活动比力相似), 以是仍需做一些相识.
xonsh 的提示符为 @, 由于它读作 "consh", 脚本文件扩展名为 .xsh, 官方界说的 markdown 代码块标签也是 xsh
克制本文末了更新, xonsh 的最高版本是 0.22.8
特别语法
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']
复制代码 若要取消一个别名, 只需:- ~ @ del aliases['la']
- ~ @ la
- xonsh: subprocess mode: command not found: 'la'
复制代码 别的, 扩展 xontrib-abbrevs (须要安装 xontrib-abbrevs 包) 还提供了一套独立的, 输入后会自动睁开的类 alias 体系, 存放于全局的 abbrevs 字典对象中- ~ @ abbrevs['ll'] = 'ls -l'
- ~ @ ls -l # 输入 ll 回车或空格后自动补全
- 总计 36
- drwxr-x--- 4 pluv wheel 4096 4月11日 12:25 Desktop
- drwxr-x--- 10 pluv wheel 4096 4月 8日 00:18 Documents
- drwxr-x--- 5 pluv wheel 4096 4月12日 09:03 Downloads
- drwxr-x--- 2 pluv wheel 4096 2月 6日 15:18 Music
- drwxr-x--- 5 pluv wheel 4096 3月26日 09:04 Pictures
- drwxr-x--- 10 pluv wheel 4096 4月 9日 19:39 Programs
- drwxr-x--- 2 pluv wheel 4096 3月10日 21:58 Public
- drwxr-x--- 2 pluv wheel 4096 2月 6日 15:18 Templates
- drwxr-x--- 3 pluv wheel 4096 2月18日 21:18 Videos
- ~ @
复制代码 路径匹配, 正则表达式和反引号
xonsh 和大多数 shell 一样, 默认利用 glob 匹配路径, 比方:- ~ @ ls
- Desktop Documents Downloads Music Pictures Programs Public Templates Videos
- ~ @ echo D*
- Desktop Documents Downloads
- ~ @
复制代码 在 xonsh 中, `` 不像在bash中一样代表历程更换. 思量到反引号自己在 python3 中已经失去了作用, 于是 xonsh 的开发者非常智慧地给反引号分配了正则路径匹配功能, 无需用户去导入并繁琐地利用 re 和 pathlib 模块
如许你就可以用反引号括住正则表达式以对路径举行正则匹配
比方:- ~ @ touch report2023.txt
- ~ @ ls `report.*\.txt`
- report2023.txt
复制代码 同理:- # 匹配 /etc 目录下所有 .conf 结尾的文件
- ls `/etc/.*\.conf`
- # 匹配 /tmp 目录下任意深度的 .log 文件
- ls `/tmp/.*\.log`
- # 匹配家目录下所有 .py 文件
- ls `~/.*\.py`
复制代码 会话对象
xonsh 利用 @ 指代当前会话, 其为一个 XonshSessionInterface 对象, 具有以下公有属性:
@.env 是一个 xonsh.environ.Env 对象, 兼容字典 API, 用于存储或设置当前会话的环境变量
@.history 是一个 xonsh.history.json.JsonHistory 对象(当利用 JSON 后端时), 用于存储汗青记录, 兼容列表 API
@.imp 是一个 xonsh.built_ins.InlineImporter 包导入器对象, 用于导入包
比方:- @ json = @.imp.json # 实际上等同于 import json
复制代码 @.lastcmd 是一个 xonsh.procs.pipelines.HiddenCommandPipeline 或 xonsh.procs.pipelines.CommandPipeline 对象, 存储上一个下令的捕获结果(无论显式或隐式捕获, 具体见下文)
子历程相干
shell 本质上是人类友爱且带下令表明功能的子历程与内建下令启动工具, xonsh 对 subprocess 的处理处罚和其他 shell 差别
发起子历程而并不举行捕获
为了克制歧义, xonsh 现实上对任何子历程都是捕获的(包罗不外包 操纵符地运行下令, 利用 $[], ![], $(), !()), 此节只是先容了一种 xonsh 不提供任何捕获后信息的子历程发起方法.
比方, 纵然你不外衣操纵符运行一个下令, 下令自己也会被隐式捕获, xonsh 会读取捕获后的 HiddenCommandPipeline(隐蔽式下令管线) 对象读取返回值, 并根据你的设置体现或不体如今你的下一个提示符, 并把谁人对象放入 @.lastcmd 中, 详情请看下下节.
xonsh 提供了 $[] 操纵符以显式发起一个子历程, 它不会捕获或隐蔽式地捕获关于子历程的任何信息给任何步伐以致 xonsh 自己(返回一个 None 对象)- ~ @ $[ls]
- Desktop Documents Downloads Music Pictures Programs Public Templates Videos
- ~ @ $[echo yeah]
- yeah
复制代码 这通常被用于脚本中, 比方只须要调用 time 下令让用户读它的输出, 又怕它和 python 的 time 包重名的情境
![] 会自动对包罗内容举行变量引用剖析后套上引号, 自己也可以包罗字符串, 但字符串内的内容将不会被剖析
一个例子:- ~ @ text = 1
- ~ @ $['ls @(text)']
- xonsh: subprocess mode: command not found: 'ls @(text)'
- ~ @
- ~ @ $[ls @(text)]
- ls: 无法访问 '1': 没有那个文件或目录
- ~ @
复制代码 另一个例子, 阐明纵然不套字符串, $[] 内的内容也不会作为 python 表达式被剖析- ~ @ $[time]
- time: missing program to run
- Try 'time --help' for more information.
- ~ @ $[time.time()]
-
- File "<stdin>", line 1
- $[time.time()]
- ^^^^
- SyntaxError: ('code: (',)
复制代码 捕获子历程信息
xonsh 利用 $() 和 !() 操纵符捕获子历程, 但它们不是等价的
$() 操纵符用于仅捕获子历程的输出
比方:- tmp @ $(ls -l)
- '总计 0\n-rw-r--r-- 1 pluv wheel 0 4月12日 11:57 iamafile\n'
复制代码 值得注意的是 xonsh 通过变量 $XONSH_SUBPROC_OUTPUT_FORMAT 来决定捕获得到的数据结构范例
默认是 'stream_lines', 即将全部输出行捕获为一个单一字符串
可将其设置为 'list_lines', 将全部输出行分行捕获为一个列表
比方- ~ @ $XONSH_SUBPROC_OUTPUT_FORMAT = 'list_lines'
- ~ @ $(ls -l)
- ['总计 36',
- 'drwxr-x--- 4 pluv wheel 4096 4月11日 12:25 Desktop',
- 'drwxr-x--- 10 pluv wheel 4096 4月 8日 00:18 Documents',
- 'drwxr-x--- 5 pluv wheel 4096 4月12日 09:03 Downloads',
- 'drwxr-x--- 2 pluv wheel 4096 2月 6日 15:18 Music',
- 'drwxr-x--- 5 pluv wheel 4096 3月26日 09:04 Pictures',
- 'drwxr-x--- 10 pluv wheel 4096 4月 9日 19:39 Programs',
- 'drwxr-x--- 2 pluv wheel 4096 3月10日 21:58 Public',
- 'drwxr-x--- 2 pluv wheel 4096 2月 6日 15:18 Templates',
- 'drwxr-x--- 3 pluv wheel 4096 2月18日 21:18 Videos']
- ~ @
复制代码 不要将 $XONSH_SUBPROC_OUTPUT_FORMAT 设置为 'list_lines' 和 'stream_lines' 之外的其他值, 否则捕获是不会工作的- ~ @ $XONSH_SUBPROC_OUTPUT_FORMAT = 'list'
- ~ @ $(ls -l)
- ~ @ # 啥也没有
复制代码 别的, $() 只会捕获 stdout 流的内容, 也就是说, 假如内容是以 stderr 流输出的, xonsh 不会捕获它, 这些内容将被输出(如下例)
以及若下令不会在 stdout 输出结果(如下例), 那么 xonsh 将视 $XONSH_SUBPROC_OUTPUT_FORMAT 来将空字符串 '' 或 空列表 [] 而不是 None 对象大概 [''] 这种东西反馈给变量作为回退结果 (应该是思量到处理处罚范例的划一性吧)- ~ @ $XONSH_SUBPROC_OUTPUT_FORMAT = 'stream_lines'
- ~ @ $(ls 不存在的目录)
- ls: 无法访问 '不存在的目录': 没有那个文件或目录 # -> 这是输出的错误信息, xonsh 没有捕获它
- '' # -> 这是捕获到的内容(一个空字符串)
- ~ @ s = $(ls 不存在的目录)
- ls: 无法访问 '不存在的目录': 没有那个文件或目录
- ~ @ s
- '' # -> 这是一个空字符串
- ~ @ $XONSH_SUBPROC_OUTPUT_FORMAT = 'list_lines'
- ~ @ s = $(ls 不存在的目录)
- ls: 无法访问 '不存在的目录': 没有那个文件或目录
- ~ @ s
- []
复制代码 对于有颜色的内容, xonsh 会捕获其控制码
可以用这个小步伐测试
[code]#include int main(){ std::cout |