在bash中用空白字符匹配字符串



基本上,我的目标是在进入ROR项目时,将rails版本作为提示段打印到终止符(终端(。

我已经找到了一种方法,如何在终止符中将其显示为自定义段,但我很难提取rails版本。为了提取ROR项目的rails版本,有一个名为Gemfile.lock的文件,其中有一个ruby宝石列表,以及它为应用程序安装的rails的确切版本。

这就是Gemfile.lock的样子:

GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.3.1)
actionpack (= 7.0.3.1)
activesupport (= 7.0.3.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.3.1)
actionpack (= 7.0.3.1)
activejob (= 7.0.3.1)
activerecord (= 7.0.3.1)
activestorage (= 7.0.3.1)
activesupport (= 7.0.3.1)
mail (>= 2.7.1)
net-imap
net-pop
....
....
rails (7.0.3.1)
actioncable (= 7.0.3.1)
actionmailbox (= 7.0.3.1)
actionmailer (= 7.0.3.1)
actionpack (= 7.0.3.1)
actiontext (= 7.0.3.1)
actionview (= 7.0.3.1)
activejob (= 7.0.3.1)
activemodel (= 7.0.3.1)
....
....
DEPENDENCIES
bootsnap
capybara
debug
importmap-rails
jbuilder
puma (~> 5.0)
rails (~> 7.0.3, >= 7.0.3.1)
redis (~> 4.0)
selenium-webdriver
....
....

我想提取的宝石是rails (7.0.3.1)

我正在处理一个.zshrc文件来提取它,到目前为止,我已经想出了这个解决方案:

ver=`awk -F' ' '$1~/^rails/{print $0}' Gemfile.lock` 

其给出以下输出

rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
rails (7.0.3.1)
rails-dom-testing (2.0.3)
rails-html-sanitizer (1.4.3)
rails (~> 7.0.3, >= 7.0.3.1) 

正如您所看到的,有多个gem包含名称rails。但我只想提取这个gemrails (7.0.3.1)的版本,它有一个前导的4个空格字符

我正在寻找的预期输出只是像这样的gem版本:不带括号的7.0.3.1,并以字符串类型返回。然后,它将被存储在一个变量中,然后我将在终端中打印出来,作为一个自定义提示段,带有自定义颜色,如:

local color="%F{#f7507b}"
# ver = ``
echo "%{$color%}$ver"

其中ver是存储了rails版本的变量。

在过去的半天里,我一直在尝试,但没有成功,我也尝试过使用[[:blank:]]&s,但它不适用于此上下文。我也尝试过使用rails -v,它输出我们所在项目目录的rails版本,但在用户没有安装Gemfile中指定的ruby版本的罕见情况下,这也会出现错误。

无论用户是否在其系统中安装了特定版本的ruby或rails,输出都应该给出应用程序使用的rails版本。所以我认为从Gemfile.lock中提取rails版本是唯一的方法。但是,如果你对这个解决方案有任何其他方法,我会洗耳恭听的!

例如,使用gnu awk可以使用带有捕获组的模式。

模式匹配:

  • ^[[:space:]]*匹配字符串开头的可选空格
  • rails[[:space:]]+匹配rails和1+空间
  • (匹配(
  • ([0-9][0-9.]*)第1组捕获,匹配数字和可选点和数字
  • )匹配)

示例:

gawk 'match($0, /^[[:space:]]*rails[[:space:]]+(([0-9][0-9.]*))/, a) {
print a[1]
}' Gemfile.lock

输出

7.0.3.1

或与awk匹配

awk '$1 == "rails" && match($2, /([0-9][0-9.]*)/) {
print substr($2, RSTART+1, RLENGTH-2)
}' Gemfile.lock

更新为只提取版本号-7.0.3.1-并存储在变量中:

$ awk '$1=="rails" {gsub(/[()]/,"",$2); print $2}' Gemfile.lock
7.0.3.1
$ ver=$(awk '$1=="rails" {gsub(/[()]/,"",$2); print $2}' Gemfile.lock)
$ typeset -p ver
declare -- ver="7.0.3.1"

与当前代码的耦合问题:

  • -F' '-不需要,因为默认字段分隔符是空白,即(多个(空格和制表符
  • 由于所需的行由每侧都有空白的字符串rails组成,因此我们可以简单地使用相等比较

awk的一些想法:

awk '{ if ($1 == "rails") print $0}' Gemfile.lock
awk '$1 == "rails" { print $0 }' Gemfile.lock
awk '$1 == "rails" { print }' Gemfile.lock
awk '$1=="rails"' Gemfile.lock 

所有这些都会生成:

rails (7.0.3.1)

对于您提出的问题,我只是想建议您不要自己解析/处理Gemfile.lock,而只需使用rails可执行文件:

rails -v | awk '{ print $2 }'

最新更新