12

Is there any way to create the regex /func:\[sync\] displayPTS/ from string func:[sync] displayPTS?

The story behind this question is that I have serval string pattens to search against in a text file and I don't want to write the same thing again and again.

 File.open($f).readlines.reject {|l| not l =~ /"#{string1}"/}
 File.open($f).readlines.reject {|l| not l =~ /"#{string2}"/}

Instead , I want to have a function to do the job:

  def filter string
          #build the reg pattern from string
          File.open($f).readlines.reject {|l| not l =~ pattern}
  end
  filter string1
  filter string2
1
  • Instead of converting your string to a regex, isn't there a search function that doesn't take a regex as param? Commented Jan 5, 2010 at 8:13

4 Answers 4

30
s = "func:[sync] displayPTS"
# => "func:[sync] displayPTS"
r = Regexp.new(s)
# => /func:[sync] displayPTS/
r = Regexp.new(Regexp.escape(s))
# => /func:\[sync\]\ displayPTS/
Sign up to request clarification or add additional context in comments.

Comments

13

I like Bob's answer, but just to save the time on your keyboard:

string = 'func:\[sync] displayPTS'
/#{string}/

2 Comments

Your solution won't work because it doesn't escape the brackets around 'sync', whereas Bob's solution does.
I think the question was more concerning how to make interpolated regexps, but fair point. updated
3

If the strings are just strings, you can combine them into one regular expression, like so:

targets = [
  "string1",
  "string2",
].collect do |s|
  Regexp.escape(s)
end.join('|')
targets = Regexp.new(targets)

And then:

lines = File.readlines('/tmp/bar').reject do |line|
  line !~ target
end

s !~ regexp is equivalent to not s =~ regexp, but easier to read.

Avoid using File.open without closing the file. The file will remain open until the discarded file object is garbage collected, which could be long enough that your program will run out of file handles. If you need to do more than just read the lines, then:

File.open(path) do |file|
  # do stuff with file
end

Ruby will close the file at the end of the block.

You might also consider whether using find_all and a positive match would be easier to read than reject and a negative match. The fewer negatives the reader's mind has to go through, the clearer the code:

lines = File.readlines('/tmp/bar').find_all do |line|
  line =~ target
end

Comments

1

How about using %r{}:

my_regex = "func:[sync] displayPTS"
File.open($f).readlines.reject { |l| not l =~ %r{#{my_regex}} }

1 Comment

That won't escape the square brackets.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.