Split and Modify Last - ruby

I have a string “shared/errors”, and I’d like for the the word “error” to be prepended with an underscore, so as to achieve “shared/_errors” Is there some ruby magic for doing this?

Assuming there is only a single slash in the string, all that is necessary is
string.sub!(%r|(?<=/)|, '_')
or, if you prefer,
string.sub!('/', '/_')
If there are multiple slashes in the string and you only want to affect the last one, then you want
string.sub!(%r|(?=[^/]*\z)|, '_')

If you only want to do this on the last occurrence of the forward slash you can insert an underscore at the index of the slash:
string.insert(string.rindex('/') + 1, '_')

Perhaps all answers are valid here, but I did see that OP references 'errors' by name. Rather than the slash.
string.gsub!('error', '_error') should change the original string, and do so, for all occurrences that may happen in the string. Of course, I have a feeling the slash is important, so perhaps the more correct string.gsub!('/error', '/_error') will do better.

Why not
path = 'shared/errors' # or whatever it is
dir, file = path.match(/^(.*\/)([^/]*)$/).captures
path = dir + "_" + file
This will get the two parts of the string:
shared/errors ==> shared/ + errors
And then patch them back together to form the desired string.

Related

Regex match anything except ending string

I'm trying to make a regex that matches anything except an exact ending string, in this case, the extension '.exe'.
Examples for a file named:
'foo' (no extension) I want to get 'foo'
'foo.bar' I want to get 'foo.bar'
'foo.exe.bar' I want to get 'foo.exe.bar'
'foo.exe1' I want to get 'foo.exe1'
'foo.bar.exe' I want to get 'foo.bar'
'foo.exe' I want to get 'foo'
So far I created the regex /.*\.(?!exe$)[^.]*/
but it doesn't work for cases 1 and 6.
You can use a positive lookahead.
^.+?(?=\.exe$|$)
^ start of string
.+? non greedily match one or more characters...
(?=\.exe$|$) until literal .exe occurs at end. If not, match end.
See demo at Rubular.com
Wouldn't a simple replacement work?
string.sub(/\.exe\z/, "")
Do you mean regex matching or capturing?
There may be a regex only answer, but it currently eludes me. Based on your test data and what you want to match, doing something like the following would cover both what you want to match and capture:
name = 'foo.bar.exe'
match = /(.*).exe$/.match(name)
if match == nil
# then this filename matches your conditions
print name
else
# otherwise match[1] is the capture - filename without .exe extension
print match[1]
end
string pattern = #" (?x) (.* (?= \.exe$ )) | ((?=.*\.exe).*)";
First match is a positive look-ahead that checks if your string
ends with .exe. The condition is not included in the match.
Second match is a positive look-ahead with the condition included in the
match. It only checks if you have something followed by .exe.
(?x) is means that white spaces inside the pattern string are ignored.
Or don't use (?x) and just delete all white spaces.
It works for all the 6 scenarios provided.

Regex to match string excluding first character

I'm writing ruby and need some help with regex. And I'm really noob in regexp.
I have a string like this
/hello/world
I would like to #gsub this string to change the second slash to %2F.
The challange for me to ignore the first slash and to change only the second slash.
I tried this one
[^/]/
but it chooses not clean slash but o/ in
/hello/world
Please, help me. Thanks!!
You can simply capture the character before the slash in a group and use that in the replacement, for example:
"/hello/world".gsub(/([^\/])\//, '\1%2F') #=> "/hello%2Fworld"
Or if you just want to match any / that appears after the first character, you can simplify this to:
"/hello/world".gsub(/(.)\//, '\1%2F') #=> "/hello%2Fworld"
Or like this:
"/hello/world".gsub(/(?<!^)\//, '%2F') #=> "/hello%2Fworld"
And now for an uglier, regexless alternative:
"/hello/world".split("/").tap(&:shift).unshift("/").join("")
I'll see myself out.
You need to use subpattern within () for find substring:
/^\/(.*)$/
or
/^.(.*)$/
this pattern excluding first character. And then replace / in this substring
(?!^\/)\/
http://rubular.com/r/IRWptAJdLs is a a working example.
change the second / to %2F:
'/hello/world'.sub /(\/.*?)\//, '\1%2F'
#=> "/hello%2Fworld"

ruby regex : match any .css filename not starting with an underscore, preceding any string

I'm trying to figure out how I can match any .css filename, not starting with an underscore, preceding any string. I found a good starting point from this question on stackoverflow (ActiveAdmin assets precompile error) :
[/^[^_]\w+\.(css|css.scss)$/]
However, this regex only matches filename.css without an underscore. I'd like to have a regex that matches any path before the filename without underscore. The following strings should match :
mystyle.css
application.css.scss
/assets/stylesheets/application.css
but the following strings should not match :
_mystyle.css
_application.css.scss
/assets/stylesheets/_application.css
Any help would be appreciated.
Something like this should work:
/(.+\/|^)[a-z0-9\.]+\.s?css$/
Not all ruby versions support it, but you coul also try a negative lookahead:
/.+\/?(?!_)\w+\.s?css$/
http://ruby-doc.org/core-2.0/Regexp.html#label-Anchors
This should work:
/^(.*?\/)?[^_]\w*\.(css|css\.scss)$/
Explanation:
(.*?\/)? # Means it accepts any characters upfront, ending with a slash,
# then the filename. The ? makes it optional.
Assuming that the input is always a file path, I would prefer to do like this:
File.basename(file_path).match(/_.*(css|scss|sass)/)
Regexps are hard to read, and so to improve your code readability is a good idea to use as few as necessary.
Also, if you are doing other matches, you might want to extract the css file extensions in other regexp like
css_exts_regexp = /(css|scss|sass)/
File.basename(file_path).match(/_.*#{css_exts_regxp}/)

Ruby regex to remove / from string

I currently have a string to remove spaces from strings, however I now need to remove forward slashes from the string too. I'm not very good with regexes and could use some help thanks. This is the current regex I have: gsub(/\s+/, "") how do I modify this to remove / ? I've played around in the console and can't seem to get it.
You have to escape the forward slash because it's a special character. Something like this:
s = "This is a line / string"
s.gsub(/[\s\/]/, '') # => "Thisisalinestring"

How to remove the extra double quote?

In a malformed .csv file, there is a row of data with extra double quotes, e.g. the last line:
Name,Comment
"Peter","Nice singer"
"Paul","Love "folk" songs"
How can I remove the double quotes around folk and replace the string as:
Name,Comment
"Peter","Nice singer"
"Paul","Love _folk_ songs"
In Ruby 1.9, the following works:
result = subject.gsub(/(?<!^|,)"(?!,|$)/, '_')
Previous versions don't have lookbehind assertions.
Explanation:
(?<!^|,) # Assert that we're not at the start of the line or right after a comma
" # Match a quote
(?!,|$) # Assert that we're not at the end of the line or right before a comma
Of course this assumes that we won't run into pathological cases like
"Mary",""Oh," she said"
If you're not on Ruby 1.9, or just get tired of regexes sometimes, split the string on ,, strip the first/last quotes, replace remaining "s with _s, re-quote, and join with ,.
(We don't always have to worry about efficiency!)
$str = '"folk"';
$new = str_replace('"', '', $str);
/* now $new is only folk, without " */
Meta-strategy:
It's likely the case that the data was manually entered inconsistently, CSV's get messy when people manually enter either field terminators (double quote) or separators (comma) into the field itself. If you can have the file regenerated, ask them to use an extremely unlikely field begin/end marker, like 5 tilde's (~~~~~), and then you can split on "~~~~~,~~~~~" and get the correct number of fields every time.
Unless you have no other choice, get the file regenerated with correct escaping. Any other approach is asking for trouble, because the insertion of unescaped quotes is lossy, and thus cannot be reliably reversed.
If you can't get the file fixed from the source, then Tim Pietzcker's regex is better than nothing, but I strongly recommend that you have your script print all "fixed" lines and check them for errors manually.

Resources