Home > Back-end >  Matching a string with whitespace character in bash
Matching a string with whitespace character in bash

Time:07-20

Basically, my goal is to print the rails version as a prompt segment to the terminator(terminal) as we enter a ROR project.

I have figured out a way how to display it as a custom segment in the terminator but I am having difficulty extracting the rails version. And to extract the rails version of a ROR project, there's a file called Gemfile.lock which has a list of ruby gems and the exact rails version it has installed for the app.

This is what a Gemfile.lock looks like:

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)
      activerecord (= 7.0.3.1)
      activestorage (= 7.0.3.1)
      activesupport (= 7.0.3.1)
      bundler (>= 1.15.0)
      railties (= 7.0.3.1)
    rails-dom-testing (2.0.3)
      activesupport (>= 4.2.0)
      nokogiri (>= 1.6)
    rails-html-sanitizer (1.4.3)
      loofah (~> 2.3)
    railties (7.0.3.1)
      actionpack (= 7.0.3.1)
      activesupport (= 7.0.3.1)
      method_source
      rake (>= 12.2)
      thor (~> 1.0)
     ....
     ....

The gem I want to extract is rails (7.0.3.1)

I am working on a .zshrc file to extract it and so far I have come up with this solution:

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

which gives the following output

      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) 

As you can see there are multiple gems that include the name rails in them. But I only want to extract the version of this gem rails (7.0.3.1) which has a leading 4 space characters in it.

The expected output I am looking for is just the version of the gem like this: 7.0.3.1 without parenthesis and as a string type. This will then be stored in a variable and then I will print it out in the terminal as a custom prompt segment with a custom color like:

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

where ver is the variable that has rails version stored in it.

I have been trying for the past half day but no luck and I have also tried using [[:blank:]] & \s but it doesn't work for this context.

CodePudding user response:

Updated to extract just the version number - 7.0.3.1 - and store in a variable:

$ 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"

Couple issues with the current code:

  • -F' ' - not necessary since the default field delimiter is white space, ie, (multiple) spaces and tabs
  • since the desired line consists of the string rails with white space on each side we can simply use an equality comparison

A few awk ideas:

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 

All of these generate:

      rails (7.0.3.1)

CodePudding user response:

Using gnu awk you might use for example a pattern with a capture group:

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

Output

7.0.3.1
  • Related