有没有办法为子串命令组合多个正则表达式?

时间:2014-03-27 12:31:35

标签: ruby regex ruby-on-rails-3

有没有办法合并我用来将多平台文件路径转换为URL的这两个正则表达式?

@image_file = "#{request.protocol}#{request.host}/#{@image_file.path.sub(/^([a-z]):\//,"")}".sub(/^\//,"")

这会处理我的Windows和* IX平台,以便将文件路径转换为URL。例如,以下两个文件路径字符串都已正确处理:

 - "c:\users\docs\pictures\image.jpg" goes to "http://localhost/users/docs/pictures/image.jpg"
 - "\home\usr_name\pictures\image.jpg" goes to "http://localhost/usr_name/pictures/image.jpg"

如果有方法可以正确组合它,我宁愿不必对字符串使用两个sub调用。

欢迎社区的建议和反馈!

2 个答案:

答案 0 :(得分:2)

您正在寻找的正则表达式是/^([a-z]:)?\//

"c:/users/docs/pictures/image.jpg".sub(/^([a-z]:)?\//, '')
=> "users/docs/pictures/image.jpg" 
"/home/usr_name/pictures/image.jpg".sub(/^([a-z]:)?\//, '')
=> "home/usr_name/pictures/image.jpg"

答案 1 :(得分:0)

作为处理文件名和URL的一些背景......

首先,Ruby不要求你在Windows文件名中使用反斜杠,所以如果你生成它们就不要打扰了。相反,依赖于IO类知道您所使用的操作系统这一事实,并将自动检测路径分隔符并为您即时转换内容。这来自the IO documentation

  如果可能,Ruby将在不同的操作系统约定之间转换路径名。例如,在Windows系统上,文件名“/gumby/ruby/test.rb”将打开为“\ gumby \ ruby​​ \ test.rb”。在Ruby字符串中指定Windows样式的文件名时,请记住转义反斜杠:

"c:\\gumby\\ruby\\test.rb"
     

我们这里的例子将使用Unix风格的正斜杠; File :: ALT_SEPARATOR可用于获取特定于平台的分隔符。

如果您正在接收来自其他来源的路径,这可以很容易地将它们规范化为Ruby喜欢的东西:

path = "c:\\users\\docs\\pictures\\image.jpg" # => "c:\\users\\docs\\pictures\\image.jpg"
puts path
# >> c:\users\docs\pictures\image.jpg

path.gsub!(/\\/, '/') if path['\\']
path # => "c:/users/docs/pictures/image.jpg"
puts path
# >> c:/users/docs/pictures/image.jpg

为方便起见,编写一个小帮手方法:

def normalize_path(p)
  p.gsub(/\\/, '/')
end

normalize_path("c:\\users\\docs\\pictures\\image.jpg") # => "c:/users/docs/pictures/image.jpg"
normalize_path("/users/docs/pictures/image.jpg") # => "/users/docs/pictures/image.jpg"

Ruby的FilePathname类在处理路径时非常有用:

foo = normalize_path(path) # => "c:/users/docs/pictures/image.jpg"

File.dirname(foo) # => "c:/users/docs/pictures"
File.basename(foo) # => "image.jpg"

File.split(foo) # => ["c:/users/docs/pictures", "image.jpg"]
path_to_file, filename = File.split(foo)
path_to_file # => "c:/users/docs/pictures"
filename # => "image.jpg"

另外还有Pathname类:

require 'pathname'
bar = Pathname.new(foo)
bar.dirname # => #<Pathname:c:/users/docs/pictures>
bar.basename # => #<Pathname:image.jpg>

Pathname是Ruby标准库中的一个实验类,它将File,FileUtils和Dir中的所有便捷方法包装成一个伞类。值得了解一下:

  

这个类的目标是以比标准Ruby提供的更简洁的方式操作文件路径信息。以下示例说明了不同之处。

     

包括File,FileTest以及Dir和FileUtils中的一些功能,这是一种不足为奇的方式。它本质上是所有这些的外观,甚至更多。

回到你的问题......

Ruby的标准库也包含URI类。它经过了很好的测试,并且是一种比简单的字符串连接更好的构建URL的方法,因为当需要对字符进行编码时可能会发生这种特性。

require 'uri'

url = URI::HTTP.build({:host => 'www.foo.com', :path => foo[/^(?:[a-z]:)?(.+)/, 1]})
url # => #<URI::HTTP:0x007fe91117a438 URL:http://www.foo.com/users/docs/pictures/image.jpg>

build方法应用语法规则以确保URL有效。

如果您需要它,此时您可以使用to_s来获取字符串化版本:

url.to_s # => "http://www.foo.com/users/docs/pictures/image.jpg"