Replace backslahes in the accented file path - ruby

I tried to replace the backslahes in file path I got from Excel file:
path = "X:\Clients\BUT_Monétique Commerçant\2Gestion\4_Suivi\Suivi_Projet"
as follows:
path.gsub!("\\","/")
or
path.gsub!("\\","\\\\")
and no one worked. Any idea how to solve that. As you see, the URL contains some accented letters.

Are you actually using the following to define path?
path = "X:\Clients\BUT_Monétique Commerçant\2Gestion\4_Suivi\Suivi_Projet"
That doesn't work, at least in Ruby 1.8.7. You need to either use single quotes, or double the backslashes to escape them.
However, once you do that, the following works for me:
irb(main):001:0> path = 'X:\Clients\BUT_Monétique Commerçant\2Gestion\4_Suivi\Suivi_Projet'
=> "X:\\Clients\\BUT_Mon\303\251tique Commer\303\247ant\\2Gestion\\4_Suivi\\Suivi_Projet"
irb(main):002:0> path.gsub!("\\","/")
=> "X:/Clients/BUT_Mon\303\251tique Commer\303\247ant/2Gestion/4_Suivi/Suivi_Projet"
If that isn't working for you, can you paste the actual code that you are running, and the results that you get?

This works for me:
path = 'X:\Clients\BUT_Monétique Commerçant\2Gestion\4_Suivi\Suivi_Projet'
path.gsub!("\\","/")
p path
#=> "X:/Clients/BUT_Monétique Commerçant/2Gestion/4_Suivi/Suivi_Projet"
Alternately, you could just split on the backslashes and let Ruby's File class determine the filesystem-appropriate separator:
path = 'X:\Clients\BUT_Monétique Commerçant\2Gestion\4_Suivi\Suivi_Projet'
old_path = path.split("\\")
new_path = File.join(old_path)
p new_path
#=> "X:/Clients/BUT_Monétique Commerçant/2Gestion/4_Suivi/Suivi_Projet"

Related

How to split a string by slash in ruby

how can i split a string "DESKTOP-AHDESI\Username" by slash in ruby 2.7.1p83
tmp = "DESKTOP-AHDESI\Username"
print tmp
tmp = tmp.split("\\")
print tmp
i got:
Ruby Error: NoMethodError undefined method `gsub!'
Problem
Your tmp variable is enclosed in double-quotes, and contains a backslash which is being interpreted as an escape rather than a character literal. You can see this easily by simply pasting your string into a REPL like irb:
"DESKTOP-AHDESI\Username" #=> "DESKTOP-AHDESIUsername"
You need to handle the backslash specially in both your String methods.
Solution
One way to handle this is to use Ruby's alternate quoting mechanism. For example:
%q(DESKTOP-AHDESI\Username).split '\\' #=> ["DESKTOP-AHDESI", "Username"]
This may not help you directly, though.
Wherever the value from tmp is coming from, you need to refactor the code to ensure that your String is properly escaped before you assign it to your variable, or otherwise pre-process it. String#dump won't really help much if the value you're assigning is unescaped before assignment, so you're going to have to fix this in whatever code you're using to generate or grab the string in the first place.
First of all, you are giving the wrong string. \ is the escape character when you use inside the "". So It will try to escape the next character U but this character doesn't have any Job so it will print U on the screen. Modify your string like below, it will work.
tmp = "DESKTOP-AHDESI\\Username"
p tmp
tmp = tmp.split("\\")
p tmp
Output
"DESKTOP-AHDESI\\Username"
["DESKTOP-AHDESI", "Username"]

Different behavior renaming a file using gsub

I'm unable to correctly rename a directory with pattern matching.
Trying to replace last occurence of old_name string with new(can be any string) in a filepath:
./old_name/*/old_name/ ==> ./old_name/*/new/
If I use a string literal like the below code, I get the desired result:
dir_name = name.gsub(/(.*)#{old_name}/, '\1new')
The problem is when I try to replace the literal '\1new' with a variable string with interpolation so I can change it to any given name:
dir_name = name.gsub(/(.*)#{old_name}/, "\1#{any_string}")
This is what I get:
./old_name/*/old_name/ ==> new
It's actually ending up as "\u0001new/" and when you puts it, that shows up as new/. The reason is because in double quote strings, you need to escape the backslash, so it makes it through to the gsub call:
dir_name = name.gsub(/(.*)#{old_name}/, "\\1#{any_string}") # => "./old_name/*/new/"

Why does my regex capture the surrounding characters?

I'm trying to separate out path elements from a URL in ruby. My URL is:
/cm/api/m_deploymentzones_getDeploymentZones.htm
And using a regex:
/\/([^\/]*)\//
The match is /cm/. I expected to see just cm, given that the / characters are explicitly excluded from the capturing group. What am I doing wrong?
I am also trying to get the next path element with:
/\/[^\/]*\/([^\/]*)\//
And this returns: /cm/api/
Any ideas?
It would be easier to use URI.parse():
require 'uri'
url = '/cm/api/m_deploymentzones_getDeploymentZones.htm'
parts = URI.parse(url).path.split('/') # ["", "cm", "api", "m_deploymentzones_getDeploymentZones.htm"]
Here's a regex matching the path components:
(?<=/).+?(?=/|$)
But you'd be better off just splitting the string on / characters. You don't need regex for this.

Insert characters at end of filename (before extension)?

I have image files that I want to append a string to the name of the file, right before the extension.
Example: example.png would turn in to example-2x.png
So, I want to insert -2x right before the extension, would could be just about any image type (png, jpg, gif, etc).
If there's an easy way to do this with Ruby, great.
Rake has a nice string extension for manipulating paths:
require 'rake/pathmap'
"images/example.png".pathmap "%X-2x%x"
#=> "images/example-2x.png"
From pathmap's docs:
%X -- Everything but the file extension.
%x -- The file extension of the path. An empty string if there is no extension.
This seems to work
img[/(\.\w+)/] = "-2x#{$1}"
img1 = 'foo.png'
img1[/(\.\w+)/] = "-2x#{$1}"
img1 #=> "foo-2x.png"
img2 = 'foo.bar.jpg'
img2[/(\.\w+)/] = "-2x#{$1}"
img2 #=> "foo-2x.png.jpg"
Use basename and extname to extract the two parts you want:
http://www.ruby-doc.org/core-2.0/File.html#method-c-basename
http://www.ruby-doc.org/core-2.0/File.html#method-c-extname
def insert_before_last_dot(str, part)
idx = str.rindex('.')
return str if (idx.nil? || idx==0)
str.clone.tap { |x| x[idx] = part.to_s + '.' }
end
insert_before_last_dot('foo.jpg', '-2px') # => "foo-2px.jpg"
insert_before_last_dot('foo.bar.jpg', '-2px') # => "foo.bar-2px.jpg"
insert_before_last_dot('foo') # => "foo"
Here's what I ended up doing that seems to work pretty well across pretty much any file type.
image = 'example.png'
ext = File.extname(image)
image_2x = image.gsub(ext, "-2x"+ext)
I dont know ruby myself, but I would expect that there is some sort of string.lastIndexOf() like in java. So you basically just find the last dot, split the string around that, and then reconcatinate it with the -2x
If you're working in a Linux environment, the rename function should work.
rename {,\-2x,*}.png
In tcsh and bash shells this expands to rename .png \-2x.png *.png
> "example.png".gsub /\.[^\.]*$/, "-2x\\0"
=> "example-2x.png"
I am sure that all of the above answers are more proper than mine but i find it effective to use the replace function...
Dir | Rename-Item -NewName {$_.name -replace ".pdf"," - 2012.pdf"}
So you just take the file extension .png and replace it with -2x.png
this should work with any file extension as you are just replacing it with the same or even a different file extension and add whatever text you want before the file extension.

Ruby: How to escape url with square brackets [ and ]?

This url:
http://gawker.com/5953728/if-alison-brie-and-gillian-jacobs-pin-up-special-doesnt-get-community-back-on-the-air-nothing-will-[nsfw]
should be:
http://gawker.com/5953728/if-alison-brie-and-gillian-jacobs-pin-up-special-doesnt-get-community-back-on-the-air-nothing-will-%5Bnsfw%5D
But when I pass the first one into URI.encode, it doesn't escape the square brackets. I also tried CGI.escape, but that escapes all the '/' as well.
What should I use to escape URLS properly? Why doesn't URI.encode escape square brackets?
You can escape [ with %5B and ] with %5D.
Your URL will be:
URL.gsub("[","%5B").gsub("]","%5D")
I don't like that solution but it's working.
encode doesn't escape brackets because they aren't special -- they have no special meaning in the path part of a URI, so they don't actually need escaping.
If you want to escape chars other than just the "unsafe" ones, pass a second arg to the encode method. That arg should be a regex matching, or a string containing, every char you want encoded (including chars the function would otherwise already match!).
If using a third-party gem is an option, try addressable.
require "addressable/uri"
url = Addressable::URI.parse("http://[::1]/path[]").normalize!.to_s
#=> "http://[::1]/path%5B%5D"
Note that the normalize! method will not only escape invalid characters but also perform casefolding on the hostname part, unescaping on unnecessarily escaped characters and the like:
uri = Addressable::URI.parse("http://Example.ORG/path[]?query[]=%2F").normalize!
url = uri.to_s #=> "http://example.org/path%5B%5D?query%5B%5D=/"
So, if you just want to normalize the path part, do as follows:
uri = Addressable::URI.parse("http://Example.ORG/path[]?query[]=%2F")
uri.path = uri.normalized_path
url = uri.to_s #=> "http://Example.ORG/path%5B%5D?query[]=%2F"
According to new IP-v6 syntax there could be urls like this:
http://[1080:0:0:0:8:800:200C:417A]/index.html
Because of this we should escape [] only after host part of the url:
if url =~ %r{\[|\]}
protocol, host, path = url.split(%r{/+}, 3)
path = path.gsub('[', '%5B').gsub(']', '%5D') # Or URI.escape(path, /[^\-_.!~*'()a-zA-Z\d;\/?:#&%=+$,]/)
url = "#{protocol}//#{host}/#{path}"
end

Resources