Search code examples
ruby-on-railsawkroutesrake

How to restrict rake routes output to URI Pattern and Controller#action columns?


In my rails 4.x app on a Mac, I call rake routes, and I get the following output:

Raw output (without awk):

> bundle exec rake routes
Prefix Verb   URI Pattern    Controller#Action                                                  
new_user_session GET    /users/sign_in(.:format)           devise/sessions#new                                       
                 PATCH  /users/password(.:format)          devise/passwords#update
new_api_user_session GET    /api/auth/sign_in(.:format)    devise_token_auth/sessions#new {:format=>:json}

I want to call rake routes, but output only the last two columns (URI Pattern and Controller#action). It is also a fact that the last two columns begin with a '/', while the first two columns never have a '/'.

Desired output:

> bundle exec rake routes | awk 'something'
URI Pattern    Controller#Action                                                  
/users/sign_in(.:format)           devise/sessions#new                                       
/users/password(.:format)          devise/passwords#update
/api/auth/sign_in(.:format)    devise_token_auth/sessions#new {:format=>:json}

I tried these approaches:

Approach 1:

> bundle exec rake routes | awk '{print $(NF-1),"\t",$NF}'
Pattern      Controller#Action
/users/sign_in(.:format)           devise/sessions#new                                       
/users/password(.:format)          devise/passwords#update
devise_token_auth/sessions#new     {:format=>:json}

The first two rows (/users/sign_in and /users/password) work fine, but the third one treats devise_token_auth/sessions#new and {:format =>:json} to be separate columns, due to default field separator being space. Also, for the same reason, the header row chopped out the word URI from URI Pattern.

Approach 2:

> bundle exec rake routes | awk '{$1=""; $2=""; print}'
URI Pattern Controller#Action
/users/sign_in(.:format)           devise/sessions#new                                       
devise/passwords#update
/api/auth/sign_in(.:format)    devise_token_auth/sessions#new {:format=>:json}

In the second approach, it works fine for the first (/users/sign_in) and third (/api/auth/sign_in) rows, but it is messed up in the second row, because there is a blank first (prefix) column.

Approach 3:

I also looked for a filter switch on rake routes, (Like the top command has -stats)? but in the routes rakefile, I couldn't find any such option.

Approach 4:

The following approach works, but it uses a different fact about the data - that we need all the content beginning with the first '/':

# rake_awk


#!/usr/bin/awk -f
{   
  search="/";
  n=split($0,array,search);
  if(n == 1) {
   print "\n", $3, $4, "\t\t\t\t\t\t\t", $5, "\n";
  }
  else {
    for (i=2;i<=n;i++) {
        if (i < n) {
          printf("/%s", array[i]);
        }
        else {
          printf("/%s\n", array[i]);
        }
    }
  }
}

And from the command line:

> bundle exec rake routes | /path/to/rake_awk

URI Pattern                         Controller#Action

/users/sign_in(.:format)           devise/sessions#new                                       
/users/password(.:format)          devise/passwords#update
/api/auth/sign_in(.:format)        devise_token_auth/sessions#new {:format=>:json}

Solution

  • Given your latest requirements and the answer you posted, this may be what you want:

    $ cat tst.awk
    NR==1 { print $3, $4 "\t" $5; next }
    { sub("[^/]+",""); sub(/ +/,"\t"); print }
    
    $ awk -f tst.awk file
    URI Pattern     Controller#Action
    /users/sign_in(.:format)        devise/sessions#new
    /users/password(.:format)       devise/passwords#update
    /api/auth/sign_in(.:format)     devise_token_auth/sessions#new {:format=>:json}
    
    $ awk -f tst.awk file | column -s $'\t' -t
    URI Pattern                  Controller#Action
    /users/sign_in(.:format)     devise/sessions#new
    /users/password(.:format)    devise/passwords#update
    /api/auth/sign_in(.:format)  devise_token_auth/sessions#new {:format=>:json}