0

I am trying to use gsub or sub on a regex passed through terminal to ARGV[].

Query in terminal: $ruby script.rb input.json "\[\{\"src\"\:\"

Input file first 2 lines:

[{
    "src":"http://something.com",
    "label":"FOO.jpg","name":"FOO",
    "srcName":"FOO.jpg"
}]
[{
    "src":"http://something123.com",
    "label":"FOO123.jpg",
    "name":"FOO123",
    "srcName":"FOO123.jpg"
}]

script.rb:

dir = File.dirname(ARGV[0])
output = File.new(dir + "/output_" + Time.now.strftime("%H_%M_%S") + ".json", "w")
open(ARGV[0]).each do |x|
x = x.sub(ARGV[1]),'')
output.puts(x) if !x.nil?
end
output.close

This is very basic stuff really, but I am not quite sure on how to do this. I tried:

  • Regexp.escape with this pattern: [{"src":".
  • Escaping the characters and not escaping.
  • Wrapping the pattern between quotes and not wrapping.
Fabian N.
  • 3,807
  • 2
  • 23
  • 46
Natacha
  • 21
  • 1
  • 4
  • I don't understand what your code is supposed to do. Could you explain it, please? It might help to include the input (a JSON file?) and the expected output. – Stefan Feb 05 '16 at 16:21
  • Possible duplicate of [Interpolating a string into a regex](http://stackoverflow.com/questions/150095/interpolating-a-string-into-a-regex) – Kristján Feb 05 '16 at 16:28
  • Read "[ask]" and "[mcve]". Show us an example of your call to your code. – the Tin Man Feb 05 '16 at 19:36

3 Answers3

2

Meditate on this:

I wrote a little script containing:

puts ARGV[0].class 
puts ARGV[1].class

and saved it to disk, then ran it using:

ruby ~/Desktop/tests/test.rb foo /abc/

which returned:

String
String

The documentation says:

The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\d' will match a backlash followed by ‘d’, instead of a digit.

That means that the regular expression, though it appears to be a regex, it isn't, it's a string because ARGV only can return strings because the command-line can only contain strings.

When we pass a string into sub, Ruby recognizes it's not a regular expression, so it treats it as a literal string. Here's the difference in action:

'foo'.sub('/o/', '') # => "foo"
'foo'.sub(/o/, '') # => "fo"

The first can't find "/o/" in "foo" so nothing changes. It can find /o/ though and returns the result after replacing the two "o".

Another way of looking at it is:

'foo'.match('/o/') # => nil
'foo'.match(/o/) # => #<MatchData "o">

where match finds nothing for the string but can find a hit for /o/.

And all that leads to what's happening in your code. Because sub is being passed a string, it's trying to do a literal match for the regex, and won't be able to find it. You need to change the code to:

sub(Regexp.new(ARGV[1]), '')

but that's not all that has to change. Regexp.new(...) will convert what's passed in into a regular expression, but if you're passing in '/o/' the resulting regular expression will be:

Regexp.new('/o/') # => /\/o\//

which is probably not what you want:

'foo'.match(/\/o\//) # => nil

Instead you want:

Regexp.new('o') # => /o/
'foo'.match(/o/) # => #<MatchData "o">

So, besides changing your code, you'll need to make sure that what you pass in is a valid expression, minus any leading and trailing /.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
0

Based on this answer in the thread Convert a string to regular expression ruby, you should use

x = x.sub(/#{ARGV[1]}/,'')
Community
  • 1
  • 1
Wand Maker
  • 18,476
  • 8
  • 53
  • 87
  • Hi, I tried string interpolation. I retried with your example and the following ARGV /\[\{\"src\"\:\"/ \[\{\"src\"\:\" src /src/ "src" to no avail. Thanks. – Natacha Feb 05 '16 at 16:28
  • Are there two regex in that string? what is `src` and `"src"` for? – Wand Maker Feb 05 '16 at 16:32
  • So weird, now I have tried on my Windows machine and it works. Just not on my Mac. I haven't done it any different. – Natacha Feb 05 '16 at 19:59
0

I tested it with this file (test.rb):

puts "You should not see any number [0123456789].".gsub(/#{ARGV[0]}/,'')

I called the file like so:

ruby test.rb "\d+"
# => You should not see any number [].
guitarman
  • 3,290
  • 1
  • 17
  • 27