I feel as if my scenario is fairly simple but that I might be overcomplicating it.

I am searching through files looking for a special condition, that is where the method .all with arguments exists. In the real world that looks like:

ba_mbn_programs = Program.ba_and_managed_bar.all(:conditions => "user_programs.user_id = #{current_user.id} and brand_id = #{brand.id}", :order => :name, :joins => [:user_programs], :select => "distinct programs.*")

I'm able to find those using ag like this:

ag '\.all\(.*\)'

That gives me a big list of file names and line numbers (here's a snippet):

4:      self.active.all(:select => ["name, #{model}.id"], :order => :name).collect{|m| [m.name, m.id]}.insert(0, ["All", nil])

So in no particular order, I need to address these lines in my editor. So what I really want to do is open up the file lib/ui_elements.rb in vim and go right to line 4.

I've learned that using vim +line_num file_name is a way to do that. However just isolating the line number and file name from the ag output has forced me to do something like this:

vim `ag '\.where\(.*\)' app | tail -1 | sed -E 's/([^:]*):([0-9]*):.*/\1 \2/' | awk -v q="+" '{print q $2, $1}'`

So that just reads the last file from that search and opens the file in vim to that line number. Surely there is a better way then this?

  • \$\begingroup\$ Why not just use the :grep command from within Vim? Perhaps what you need is a Vim skill (consult Vi and Vim) rather than a code review. \$\endgroup\$ Jun 8, 2016 at 17:04

1 Answer 1


You could simplify the vim call like this:

vim $(ag '\.where\(.*\)' app | sed -nE '$s/([^:]*):([0-9]*):.*/+\2 \1/p')

That is, no need for the awk to print the matched filename and line number in reverse, you can reverse in the sed, and also prefix the number with + there.

I dropped the tail -1, by using the -n flag of sed to not print output by default, added $ in front of the s/// command to apply for only the last line of input, and the /p flag to print after substitution. Although this has the benefit of eliminating a tail process in the middle, it has the disadvantage that it's a bit harder to understand. So you can put back tail -n 1 (more portable than tail -1) if you prefer.

I also changed the obsolete `...` to $(...).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.