Rubish:用纯 Ruby 编写的 Unix shell

2026-05-23 1 阅读 winebarrel
Rubish 用纯 Ruby 编写的 UNIX shell。 Shell 语法被解析并编译为 Ruby 代码,然后由 Ruby VM 执行。概念 完全兼容 Bash Rubish 支持 bash 的所有功能,并且 shell 语法完全兼容。您无需修改​​即可运行现有的 bash 脚本。如果您发现任何 bash 脚本在垃圾中不起作用,我们认为它是一个错误,所以请报告它!深度 Ruby 集成 Rubish 不仅仅是一个用 Ruby 实现的 shell,而是一个深度集成 Ruby 的 shell。您可以无缝地混合 shell 命令和 Ruby 代码,甚至可以在 shell 脚本中使用 Ruby 的强大功能,例如块、迭代器和库。安装 Homebrew (macOS)brew tap amatsuda/rubishbrew install --HEAD rubish 来自源代码 git clone https://github.com/amatsuda/rubish.git cd rubishbundle installbundle exec exe/rubish bin/rubish 是一个小型 bash 启动器,可以自行查找可用的 Ruby(探测 ~/.rbenv/shims/ruby 、 /opt/homebrew/bin/ruby 、 /usr/local/bin/ruby 、系统 Ruby;荣誉 $RUBY )。当捆绑器不存在时使用它 - 例如作为登录 shell,从 .app 捆绑包或任何 PATH 可能最小的地方: ./bin/rubish RUBY=/opt/homebrew/opt/ruby@3.4/bin/ruby ./bin/rubish # 显式覆盖 用法 启动交互式 shell:rubish 运行单个命令:rubish -c ' echo hello ' 运行脚本:rubish script.sh 或者您甚至可以将其用作登录 shell!设置为登录 shell echo " $( which rubish ) " | sudo tee -a /etc/shells chsh -s "$(which rubish)" Bash 之外的功能 Ruby 条件 通过将 Ruby 表达式包装在 {} 中,将它们用作 if、while 和 Until 中的条件。 Shell 变量会自动绑定为 Ruby 表达式中的局部变量: COUNT=5 if { count.to_i > 3 } echo ' count is greater than 3 ' end while { count.to_i > 0 } echo $COUNT COUNT= $(( COUNT - 1 )) did Ruby 方法调用风格 除了带有空格的传统 UNIX 风格之外,还可以使用带括号的 Ruby 方法调用语法来调用命令: # 这些是等效的: ls -la ls( ' -la ' ) # 参数可以作为方法参数传递: cat(file.txt) grep( 'pattern ' , file.txt) 方法链接 命令可以使用点表示法与 Ruby 方法链接起来,形成管道。链必须通过带括号的调用、数组文字或块来打开 - 一旦进入链上下文,后续方法就可以是裸露的: sort` ls ().sort # 等价于 `ls |排序| uniq` ls ().sort.uniq # 相当于`cat file.txt | grep error` cat(file.txt).grep(/error/) # 链可以与块组合(参见下面的“Ruby 迭代器块”) ls.select { it.end_with ? ( ' .rb ' ) }.each { | f |第一个段需要括号,因为裸露的 cmd.method 与路径和点文件名( ./script.sh , file.tar.gz )不明确 - 一旦 () 确认了方法调用形式,词法分析器就知道它可以安全链接。 Ruby 迭代器块 Ruby 迭代器方法( .each 、 .map 、 .select 、 .detect )可以使用块来逐行处理命令输出: f |放置 f.upcase } cat(file.txt).map { |线 | line.strip } ls.select { it.end_with ? ( ' .rb ' ) } 内联 Ruby 求值 任何以大写字母开头的行都会直接作为 Ruby 代码求值。这意味着您可以直接从 shell 提示符使用 Ruby 类、方法和表达式,无需任何特殊语法: rubish$ Time.now => 2025-01-01 12:00:00 +0900 rubish$ Dir.glob('*.rb').sort => ["Gemfile", "Rakefile"] rubish$ ENV['HOME'] => "/Users/you" Ruby 数组和正则表达式文字Ruby 数组文字可以直接在 shell 上下文中使用。 Rubish 自动将它们与 [a-z] 等全局模式区分开来: rubish$ [1, 2, 3].map { |x| x * x } => [1, 4, 9] Lambda 表达式 您可以通过使用 lambda 表达式 ( -> { } ) 包围任何 Ruby 代码来执行该代码: rubish$ -> { 2 ** 10 } => 1024 Ruby 风格的函数定义 除了标准 shell 函数语法之外,rubish 还支持带有命名参数和 splat args 的 Ruby 风格 def...end: defgreet(name) echo " Hello, $name " end def log(level, * messages) echo " [ $level ] $messages " endgreet world # => Hello, world 自定义 Ruby 提示 将提示定义为 Ruby 函数,以实现完全编程控制。该函数会在每次提示渲染时调用,因此可以包含动态内容: def rubish_promptbranch = ` gitbranch --show-current 2> /dev/null ` .strip dir = Dir.pwd.sub(ENV[ ' HOME ' ], ' ~ ' ) " \e[36m#{dir}\e[0m \e[33m#{branch}\e[0m $ " end def rubish_right_prompt Time.now.strftime( ' %H:%M:%S ' ) end 您还可以将传统的 PS1 / RPROMPT 变量与 bash ( \X ) 或 zsh ( %X ) 转义码一起使用。延迟加载 缓慢的 shell 初始化(例如 rbenv init 、 nvm 、 pyenv )可以使用lazy_load推迟到后台线程。该块立即在后台运行,其结果(一串 shell 代码)将在下一个提示之前应用。这使得 shell 能够即时启动: # In ~/.rub