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

1

6

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?

Aveyron answered 4/10, 2013 at 4:47 Comment(0)
A
10

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"

Annunciator answered 4/10, 2013 at 4:54 Comment(2)
That worked great! Thanks for the help Tin Man. I was not aware of the english module ;)Aveyron
Yup I've used grep in the past but not for that purpose, I'll check it out. Also thanks for trimming down the loop. Looks a lot better!Aveyron

© 2022 - 2024 — McMap. All rights reserved.