开发者生态
morning
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