fetch content between _(" ") in ruby - ruby

I want to fetch all the strings between _(" ") from my file.
How may i fetch that?

Assuming there are no quotation marks nested within the string you're looking for, you want to load the file into a string
str=File.read("/path/to/file")
Then scan the string using a regular expression. The following regular expression should do the trick. It looks for the characters _(" (the open parentheses here is escaped, because parentheses have a special meaning in regular expressions). The next parentheses starts a capturing group (so that the text of the string will be stored in the special variable $1. Then it finds a string of consecutive characters until the first quotation mark. Then it ends the capturing group (with an unescaped close parentheses) looks for a ") to finish the expression.
/_\("([^"]*)"\)/
To use it
str.scan( /_\("([^"]*)"\)/ ) do
puts $1
end

Related

Ruby method gsub with string '+'

I've found interesting thing in ruby. Do anybody know why is behavior?
tried '+'.gsub!('+', '\+') and expected "\\+" but got ""(empty string)
gsub is implemented, after some indirection, as rb_sub_str_bang in C, which calls rb_reg_regsub.
Now, gsub is supposed to allow the replacement string to contain backreferences. That is, if you pass a regular expression as the first argument and that regex defines a capture group, then your replacement string can include \1 to indicate that that capture group should be placed at that position.
That behavior evidently still happens if you pass an ordinary, non-regex string as the pattern. Your verbatim string obviously won't have any capture groups, so it's a bit silly in this case. But trying to replace, for instance, + with \1 in the string + will give the empty string, since \1 says to go get the first capture group, which doesn't exist and hence is vacuously "".
Now, you might be thinking: + isn't a number. And you'd be right. You're replacing + with \+. There are several other backreferences allowed in your replacement string. I couldn't find any official documentation where these are written down, but the source code does quite fine. To summarize the code:
Digits \1 through \9 refer to numbered capture groups.
\k<...> refers to a named capture group, with the name in angled brackets.
\0 or \& refer to the whole substring that was matched, so (\0) as a replacement string would enclose the match in parentheses.
A backslash followed by a backtick (I have no idea how to write that using StackOverflow's markdown) refers to the entire string up to the match.
\' refers to the entire string following the match.
\+ refers to the final capture group, i.e. the one with the highest number.
\\ is a literal backslash.
(Most of these are based on Perl variables of a similar name)
So, in your examples,
\+ as the replacement string says "take the last capture group". There is no capture group, so you get the empty string.
\- is not a valid backreference, so it's replaced verbatim.
\ok is, likewise, not a backreference, so it's replaced verbatim.
In \\+, Ruby eats the first backslash sequence, so the actual string at runtime is \+, equivalent to the first example.
For \\\+, Ruby processes the first backslash sequence, so we get \\+ by the time the replacement function sees it. \\ is a literal backslash, and + is no longer part of an escape sequence, so we get \+.

Single backslash for Ruby gsub replacement value?

Does anyone know how to provide a single backslash as the replacement value in Ruby's gsub method? I thought using double backslashes for the replacement value would result in a single backslash but it results in two backslashes.
Example: "a&bsol;b".gsub("&bsol;", "\\")
Result: a\\b
I also get the same result using a block:
Example: "a&bsol;b".gsub("&bsol;"){"\\"}
Result: a\\b
Obviously I can't use a single backslash for the replacement value since that would just serve to escape the quote that follows it. I've also tried using single (as opposed to double) quotes around the replacement value but still get two backslashes in the result.
EDIT: Thanks to the commenters I now realize my confusion was with how the Rails console reports the result of the operation (i.e. a\\b). Although the strings 'a\b' and 'a\\b' appear to be different, they both have the same length:
'a\b'.length (3)
'a\\b'.length (3)
You can represent a single backslash by either "\\" or '\\'. Try this in irb, where
"\\".size
correctly outputs 1, showing that you indeed have only one character in this string, not 2 as you think. You can also do a
puts "\\"
Similarily, your example
puts("a&bsol;b".gsub("&bsol;", "\\"))
correctly prints
a\b

ruby sub when replacement string starts with \0

In ruby, sub does not allow to replace a string by another one starting with '\0'.
'a'.sub('a','\\0b')
Returns:
'ab'
The doc says that \0 is interpreted as a backreference, but as the first parameter is not a Regexp, I don't understand why it works like that.
If you want your second argument to be interpreted as a plain String you can escape it like:
'a'.sub('a', Regexp.escape('\0b'))
or
'a'.sub('a', '\\\0b')
both returns:
"\\0b"
Explanation about this behaviour can be found in documentation
sub(pattern, replacement) → new_str
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 backslash followed by 'd', instead of a digit.
If replacement is a String it will be substituted for the matched
text. It may contain back-references to the pattern's capture groups
of the form "\d", where d is a group number, or "\k<n>", where n is a
group name. If it is a double-quoted string, both back-references must
be preceded by an additional backslash. However, within replacement
the special match variables, such as $&, will not refer to the current
match. If replacement is a String that looks like a pattern's capture
group but is actually not a pattern capture group e.g. "\'", then it
will have to be preceded by two backslashes like so "\'".

Need to match a string containing the string file: and report in the string

Need to match a string containing the string "file://\\" and "report" in the string.
if i use the regular expression (file://\\\\)(.*)\\\\report\\\\(.*) it is working fine.
but, if i use the expression (file://\\\\)(.*)\\report\\(.*) it is giving errors.
My question is why do need to use four back slashes(\\\\) to do a match for one back slash present before and after the report string.
*wstring target(L"file://\\\\Example\\report\\001");
wsmatch wideMatch;
wregex wrx(L"(file://\\\\)(.*)\\\\report\\\\(.*)");
if (regex_match(target.cbegin(), target.cend(), wideMatch, wrx))
wcout << L"The matching text is:" << wideMatch.str() << endl;*
can some one please answer. Thanks in advance...
Backslashes are special in both string literals and in regular expressions. To match a backslash in a regular expression you need to escape it, by adding a second backslash. And to have two backslashes in a string literal then you need to escape both of them leading to you needing four backslashes.

Backslash + captured group within Ruby regular expression

How do I excape a backslash before a captured group?
Example:
"foo+bar".gsub(/(\+)/, '\\\1')
What I expect (and want):
foo\+bar
what I unfortunately get:
foo\\1bar
How do I escape here correctly?
As others have said, you need to escape everything in that string twice. So in your case the solution is to use '\\\\\1' or '\\\\\\1'. But since you asked why, I'll try to explain that part.
The reason is that replacement sequence is being parsed twice--once by Ruby and once by the underlying regular expression engine, for whom \1 is its own escape sequence. (It's probably easier to understand with double-quoted strings, since single quotes introduce an ambiguity where '\\1' and '\1' are equivalent but '\' and '\\' are not.)
So for example, a simple replacement here with a captured group and a double quoted string would be:
"foo+bar".gsub(/(\+)/, "\\1") #=> "foo+bar"
This passes the string \1 to the regexp engine, which it understands as a reference to a capture group. In Ruby string literals, "\1" means something else entirely (ASCII character 1).
What we actually want in this case is for the regexp engine to receive \\\1. It also understands \ as an escape character, so \\1 is not sufficient and will simply evaluate to the literal output \1. So, we need \\\1 in the regexp engine, but to get to that point we need to also make it past Ruby's string literal parser.
To do that, we take our desired regexp input and double every backslash again to get through Ruby's string literal parser. \\\1 therefore requires "\\\\\\1". In the case of single quotes one slash can be omitted as \1 is not a valid escape sequence in single quotes and is treated literally.
Addendum
One of the reasons this problem is usually hidden is thanks to the use of /.+/ style regexp quotes, which Ruby treats in a special way to avoid the need to double escape everything. (Of course, this doesn't apply to gsub replacement strings.) But you can still see it in action if you use a string literal instead of a regexp literal in Regexp.new:
Regexp.new("\.").match("a") #=> #<MatchData "a">
Regexp.new("\\.").match("a") #=> nil
As you can see, we had to double-escape the . for it to be understood as a literal . by the regexp engine, since "." and "\." both evaluate to . in double-quoted strings, but we need the engine itself to receive \..
This happens due to a double string escaping. You should use 5 slashes in this case.
"foo+bar".gsub(/([+])/, '\\\\\1')
Adding \ two more times escapes this properly.
irb(main):011:0> puts "foo+bar".gsub(/(\+)/, '\\\\\1')
foo\+bar
=> nil

Resources