I have a string
str = "'${1:textbox}',[${2:x},${3:y},${4:w},${5:h}]"
and I would like to replace all , between [ and ] with a single space.
I have attempted to use something like
str.gsub!(/(?<=\[)\,*?(?=\])/," ")
without success. However, if I replace \, in my expression with ., I get the expected output:
str.gsub!(/(?<=\[).*?(?=\])/," ")
== "'${1:textbox}',[ ]"
Could someone please explain the proper regex technique to use in this situation, and perhaps also explain why the examples I have posted above have failed and succeeded?
I am using ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin10.8.0]
It may be possible to do this with a single regex, but even if it is, I can guarantee it'll be ugly beyond description. It's a lot simpler to use "nested" substitution - use one gsub to find bracketed substrings, and then use another to swap out the commas:
str.gsub(/\[.*?\]/) do |substr|
substr.gsub(',', ' ')
end
I'm afraid I can't explain why your attempts have failed - neither of them would run for me (ruby 1.8.7 / irb 0.9.5). IRB gave errors that vaguely said "Bad regexp syntax." And I can't quite grok how they're supposed to work (edit: mu is too short has an awesome breakdown in his answer - check that out). Hope this is helpful anyway!
This regex:
/(?<=\[)\,*?(?=\])/
is looking for an opening bracket followed by a sequence of commas (of any length) followed by a closing bracket. That means things like this:
[]
[,]
[,,,,,,,,,,,]
Your string doesn't look like that so your first gsub! doesn't do anything. If you do this:
'[,,,,,,]'.gsub(/(?<=\[),*?(?=\])/, " ")
You'll get a '[ ]' for your troubles.
Your second regex:
/(?<=\[).*?(?=\])/
works because .*? matches anything (subject to newlines and /m and /s modifiers of course) and the portion of your string between [ and ] certainly qualifies as anything.
If you're trying to produce this:
"'${1:textbox}',[${2:x} ${3:y} ${4:w} ${5:h}]"
then I'd go with Xavier Holt's nested gsub approach, that's simple and clean.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to write \1 in a string, but I can't do it. I would appreciate if somebody helped me with this strange behaviour. Here is an example with some explaining.
EDIT: Adding example output
puts "\1 <- null"
puts "\\1 <- slash one"
works!
but typing
"\1"
"\\1"
in the irb command line yields
"\1"
=> "\u0001
"\\1"
=> "\\1"
There are a few ways to get it:
"\\1"
'\1'
?\\ + ?1
Remember that the way it will show up is always "\\1", which means literal backslash, one, which is what you want. The way to know that this is correct is to use puts:
puts "\\1"
# => \1
Inside of double-quoted strings, backslashes have significant meaning. \n means the newline character. In single quoted strings, that's two characters: backslash and n.
You can even test this:
"\\1".chars
# => ["\\", "1"]
'\1'.chars
# => ["\\", "1"]
So you can see Ruby is interpreting that as two characters, not three. Don't be fooled by the second backslash inside a double-quoted string. That's how a literal backslash is represented.
Have you tried puts '\1'? (single quotes instead of double)
I'm not 100% sure what you're asking but if that helps, cheers.
Your command line shows "\1" because irb does .inspect on the object, which escapes the string. So essentially \1 is properly stored, but when it's displaying it, it adds another \ to indicate to you that it's escaped
When I'm in IRB and type \1, the value returned is \u0001 which is Ruby's way of
representing the character.
When I write puts('\1), the behavior is the same in IRB and when running
a script. I see a unicode character map as follows
0 0
0 1
This won't be the same output on all platforms (it depends on how unicode is
displayed). So that's probably why you see no output on the repl.it example.
How do I make the parameter file of the method sound become the file name of the .fifo >extension using single quotes? I've searched up and down, and tried many different >approaches, but I think I need a new set of eyes on this one.
def sound(file)
#cli.stream_audio('audio\file.fifo')
end
Alright so I finally got it working, might not be the correct way but this seemed to do the trick. First thing, there may have been some white space interfering with my file parameter. Then I used the File.join option that I saw posted here by a few different people.
I used a bit of each of the answers really, and this is how it came out:
def sound(file)
file = file.strip
file = File.join('audio/',"#{file}.fifo")
#cli.stream_audio(file) if File.exist? file
end
Works like a charm! :D
Ruby interpolation requires that you use double quotes.
Is there a reason you need to use single quotes?
def sound(FILE)
#cli.stream_audio("audio/#{FILE}.fifo")
end
As Charles Caldwell stated in his comment, the best way to get cross-platform file paths to work correctly would be to use File.join. Using that, your method would look like this:
def sound(FILE)
#cli.stream_audio(File.join("audio", "#{FILE}.fifo"))
end
Your problem is with your usage of file path separators. You are using a \. Whereas this may not seem like a big deal, it actually is when used in Ruby strings.
When you use \ in a single quoted string, nothing happens. It is evaluated as-is:
puts 'Hello\tWorld' #=> Hello\tWorld
Notice what happens when we use double quotes:
puts "Hello\tWorld" #=> "Hello World"
The \t got interpreted as a tab. That's because, much like how Ruby will interpolate #{} code in a double quote, it will also interpret \n or \t into a new line or tab. So when it sees "audio\file.fifo" it is actually seeing "audio" with a \f and "ile.fifo". It then determines that \f means 'form feed' and adds it to your string. Here is a list of escape sequences. It is for C++ but it works across most languages.
As #sawa pointed out, if your escape sequence does not exist (for instance \y) then it will just remove the \ and leave the 'y'.
"audio\yourfile.fifo" #=> audioyourfile.fifo
There are three possible solutions:
Use a forward slash:
"audio/#{file}.fifo"
The forward slash will be interpreted as a file path separator when passed to the system. I do most my work on Windows which uses \ but using / in my code is perfectly fine.
Use \\:
"audio\\#{file}.fifo"
Using a double \\ escapes the \ and causes it to be read as you intended it.
Use File.join:
File.join("audio", "#{file}.fifo")
This will output the parameters with whatever file separator is setup as in the File::SEPARATOR constant.
I am a newbie in Ruby, I'm using version 1.9.3. I have the following regular expression:
/\\\//
As far as I know, it should match a string which has the characters '\' and '/', one following the other, right?
I am using the following code in order to get true in case the regex matches the string or symbol in the far right:
!(regex !~ :"string or symbol to match")
Because using =~ gives me the index of the match and I simply want a boolean. Besides, I'm trying to see how ugly or hackish can Ruby look compared to C :P
When I try to match the symbol :\/ the IRB prompt changes to an asterisk, and returns nothing. Why?
When I try to match the string "\/" my little ugly snippet returns false. Why?
The symbol :\/ is not a valid symbol. You could do :'\/' if you wanted a symbol version of the string '\/'. And when you feed it "\/" it is false because that has double quotes so it is actually the string '/' so you actually want either '\/' or "\\/".
Finally, it's better code and convention to do your test like so:
!!(regex =~ :'\/')
!!(regex =~ '\/')
!!(regex =~ "\\/")
I'm trying the same super simple regex on Rubular.com and my VM Linux with Ruby 1.9.2 I dont' know why I'm getting different outputs:
VM:
my_str = "Madam Anita"
puts my_str[/\w/]
this Outputs: Madam
on Rubular it outputs: MadamAnita
Rubular:
http://www.rubular.com/r/qyQipItdes
I would love some help. I stuck here. I will not be able to test my code for the hw1.
No, it doesn't really. It matches all characters in "Madam" and "Anita", but not the space. The problem you are having is that my_str[/\w/] only returns a single match for the given regular expression, whereas Rubular highlights all possible matches.
If you need all occurrences, you could do this:
1.9.3p194 :002 > "Madam Anita".scan(/\w+/)
=> ["Madam", "", "Anita", ""]
Actually, \w matches a single character. The result in Rubular contains spaces between adjacent characters to tell you this (though I wish they'd also make the highlighting more obvious...). Compare with the output from matching \w+, which matches two strings (Madam and Anita).
I'm trying to learn RegEx in Ruby, based on what I'm reading in "The Rails Way". But, even this simple example has me stumped. I can't tell if it is a typo or not:
text.gsub(/\s/, "-").gsub([^\W-], '').downcase
It seems to me that this would replace all spaces with -, then anywhere a string starts with a non letter or number followed by a dash, replace that with ''. But, using irb, it fails first on ^:
syntax error, unexpected '^', expecting ']'
If I take out the ^, it fails again on the W.
>> text = "I love spaces"
=> "I love spaces"
>> text.gsub(/\s/, "-").gsub(/[^\W-]/, '').downcase
=> "--"
Missing //
Although this makes a little more sense :-)
>> text.gsub(/\s/, "-").gsub(/([^\W-])/, '\1').downcase
=> "i-love-spaces"
And this is probably what is meant
>> text.gsub(/\s/, "-").gsub(/[^\w-]/, '').downcase
=> "i-love-spaces"
\W means "not a word"
\w means "a word"
The // generate a regexp object
/[^\W-]/.class
=> Regexp
Step 1: Add this to your bookmarks. Whenever I need to look up regexes, it's my first stop
Step 2: Let's walk through your code
text.gsub(/\s/, "-")
You're calling the gsub function, and giving it 2 parameters.
The first parameter is /\s/, which is ruby for "create a new regexp containing \s (the // are like special "" for regexes).
The second parameter is the string "-".
This will therefore replace all whitespace characters with hyphens. So far, so good.
.gsub([^\W-], '').downcase
Next you call gsub again, passing it 2 parameters.
The first parameter is [^\W-]. Because we didn't quote it in forward-slashes, ruby will literally try run that code. [] creates an array, then it tries to put ^\W- into the array, which is not valid code, so it breaks.
Changing it to /[^\W-]/ gives us a valid regex.
Looking at the regex, the [] says 'match any character in this group. The group contains \W (which means non-word character) and -, so the regex should match any non-word character, or any hyphen.
As the second thing you pass to gsub is an empty string, it should end up replacing all the non-word characters and hyphens with empty string (thereby stripping them out )
.downcase
Which just converts the string to lower case.
Hope this helps :-)
You forgot the slashes. It should be /[^\W-]/
Well, .gsub(/[^\W-]/,'') says replace anything that's a not word nor a - for nothing.
You probably want
>> text.gsub(/\s/, "-").gsub(/[^\w-]/, '').downcase
=> "i-love-spaces"
Lower case \w (\W is just the opposite)
The slashes are to say that the thing between them is a regular expression, much like quotes say the thing between them is a string.