首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用圆括号从Ruby运行Bash :意外令牌靠近'(‘)

用圆括号从Ruby运行Bash :意外令牌靠近'(‘)
EN

Stack Overflow用户
提问于 2015-02-05 04:25:16
回答 1查看 1.1K关注 0票数 0

我正在编写一个Ruby脚本,它可以执行一些简单的git命令。我想列出我的应用程序目录中没有的所有文件更改。

运行以下命令以获取终端中的所有更改:

代码语言:javascript
运行
复制
git ls-files -m

产量:

代码语言:javascript
运行
复制
config/environment.rb
app/models/site.rb

在终端中使用通配符异常运行:

代码语言:javascript
运行
复制
git ls-files -m !(app)

产量:

代码语言:javascript
运行
复制
config/environment.rb

使用以下方法在Ruby中执行相同的操作:

代码语言:javascript
运行
复制
`git ls-files -m !(app)`

产量:

代码语言:javascript
运行
复制
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `git ls-files -m !(app)'

我试过增加双逃逸:

代码语言:javascript
运行
复制
`git ls-files -m \\!\\(app\\)`

不会产生错误,只会产生空的结果。

我也试过使用Shellword:

代码语言:javascript
运行
复制
require 'shellwords'
`git ls-files -m #{Shellwords.escape("!(app)")}`

不会产生错误,只会产生空的结果。

使用%x[]语法的行为也与backticks完全一样,但似乎不像我所希望的那样工作。

有什么想法吗?如何通过在Ruby中运行git ls-files -m !(app)获得相同的结果?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-05 04:42:19

!(app)是一个bash扩展的全局。所以有两个问题:

  1. ruby使用sh来执行系统命令,而不是bash。(您可以在错误消息中看到这一点,该消息声称来自sh:。)但是,由于您的sh是由bash实现的,所以您确实可以使用bash,但有一个小问题:当bash作为sh运行时,它会禁用许多特定于bash的特性。
  2. 即使是bash,也很可能没有执行shopt -s extglob,这是!(app)和其他扩展全局运行所必需的。默认情况下,扩展全局不启用,但是一些发行版(例如,ubuntu)启用它们以实现选项卡完成,因此您可能在交互式shell中启用了它们。但是,由于ruby没有调用交互式shell,很可能没有执行带有shopt -s extglob命令的bash启动文件。

所有这一切都不可能通过红宝石使用命令,但它肯定会使生活复杂化。例如,一个可能的解决方法是启用BASHOPTS并强制bash运行:

代码语言:javascript
运行
复制
`env BASHOPTS=$BASHOPTS:extglob bash -c 'git ls-files -m !(app)'`

这可能比使用grep -v过滤掉不需要的目录名的替代解决方案复杂得多。

使用env设置env实际上只有在/bin/sh实际上是bash的情况下才能工作,因此在执行的命令中直接设置shopt可能更好。这是直截了当的,但也有一个小问题;您需要在shopt命令和扩展glob的使用之间引入一条换行符,因为bash标记一次命令一行(如果extglob在标记时没有设置,那么(就是一个元字符)。

这似乎是可行的:

代码语言:javascript
运行
复制
`bash -c "shopt -s extglob\ngit ls-files -m !(app)"`
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28336202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档