Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I print the line number of the file I am working with via ARGV?

I'm currently opening a file taken at runtime via ARGV:

File.open(ARGV[0]) do |f|
  f.each_line do |line|

Once a match is found I print output to the user.

if line.match(/(strcpy)/i)
   puts "[!] strcpy does not check for buffer overflows when copying to destination."
   puts "[!] Consider using strncpy or strlcpy (warning, strncpy is easily misused)."
   puts " #{line}"
end

I want to know how to print out the line number for the matching line in the (ARGV[0]) file.

Using print __LINE__ shows the line number from the Ruby script. I've tried many different variations of print __LINE__ with different string interpolations of #{line} with no success. Is there a way I can print out the line number from the file?

like image 375
nanotechz9l Avatar asked Oct 04 '13 04:10

nanotechz9l


1 Answers

When Ruby's IO class opens a file, it sets the $. global variable to 0. For each line that is read that variable is incremented. So, to know what line has been read simply use $..

Look in the English module for $. or $INPUT_LINE_NUMBER.

We can also use the lineno method that is part of the IO class. I find that a bit more convoluted because we need an IO stream object to tack that onto, while $. will work always.

I'd write the loop more simply:

File.foreach(ARGV[0]) do |line|

Something to think about is, if you're on a *nix system, you can use the OS's built-in grep or fgrep tool to greatly speed up your processing. The "grep" family of applications are highly optimized for doing what you want, and can find all occurrences, only the first, can use regular expressions or fixed strings, and can easily be called using Ruby's %x or backtick operators.

puts `grep -inm1 abacus /usr/share/dict/words`

Which outputs:

34:abacus

-inm1 means "ignore character-case", "output line numbers", "stop after the first occurrence"

like image 179
the Tin Man Avatar answered Oct 31 '22 18:10

the Tin Man