【问题标题】:How to combine Ruby regexp conditions如何组合 Ruby 正则表达式条件
【发布时间】:2018-04-26 05:53:23
【问题描述】:

我需要检查一个字符串是否是有效的图像 url。 我想检查字符串的开头和字符串的结尾,如下所示:

  • 必须以 http(s) 开头:
  • 必须以 .jpg|.png|.gif|.jpeg 结尾

到目前为止,我有:

(https?:)

我似乎无法指出字符串 \A 的开头、组合模式和测试字符串的结尾。

测试字符串:

"http://image.com/a.jpg"
"https://image.com/a.jpg"
"ssh://image.com/a.jpg"
"http://image.com/a.jpeg"
"https://image.com/a.png"
"ssh://image.com/a.jpeg"

请看http://rubular.com/r/PqERRim5RQ

使用 Ruby 2.5

【问题讨论】:

  • 因此,在答案部分中的人们正在争论您的“测试字符串”是否是 (1) 许多字符串,每行一个,没有空格或 (2 ) 一个单个字符串,其中正则表达式必须匹配每一行。您可以编辑问题以澄清这一点吗?

标签: ruby-on-rails ruby regex


【解决方案1】:

使用您自己的演示,您可以使用

^https?:\/\/.*(?:\.jpg|\.png|\.gif|\.jpeg)$

the modified demo


甚至可以将其简化为:
^https?:\/\/.*\.(?:jpe?g|png|gif)$

a demo for the latter as well


这基本上在两侧使用锚点(^$),指示字符串的开始/结束。此外,请记住,如果您想要 .,则需要转义点 (\.)。
cmets 部分存在相当多的歧义,所以让我澄清一下:
^  - is meant for the start of a string 
     (or a line in multiline mode, but in Ruby strings are always in multiline mode)
$  - is meant for the end of a string / line
\A - is the very start of a string (irrespective of multilines) 
\z - is the very end of a string (irrespective of multilines) 

【讨论】:

  • 这显然匹配"foo\nhttp.....jpg\nbar",它既不以"http"开头也不以"jpg"结尾。 始终使用 \A\z 锚点,而不是 ^$,除非您完全了解情况。
  • 我认为你不需要第二组:^https?:\/\/.*\.(?:jpe?g|png|gif)$
  • @revo 我擅长阅读 OP 的第一句话。它指出:“我需要检查 a string is 是否有效的图像 url。”
  • @mudasobwa 我希望你擅长阅读 OP 提供的演示,其中每个 URL 都在一行中?
  • @revo:谢谢,这正是使用^$ 而不是\A\Z 的意义所在。
【解决方案2】:

你可以使用

reg = %r{\Ahttps?://.*\.(?:png|gif|jpe?g)\z}

重点是:

  1. 在在线正则表达式测试人员测试时,您正在测试单个多行字符串,但在现实生活中,您将验证行作为单独字符串。因此,在这些测试人员中,使用^$,在实际代码中,使用\A\z
  2. 要匹配字符串而不是行,您需要 \A\z 锚点
  3. 如果您的模式中有很多 /,请使用 %r{pat} 语法,这样会更简洁。

Online Ruby test:

urls = ['http://image.com/a.jpg',
        'https://image.com/a.jpg',
        'ssh://image.com/a.jpg',
        'http://image.com/a.jpeg',
        'https://image.com/a.png',
        'ssh://image.com/a.jpeg']
reg = %r{\Ahttps?://.*\.(?:png|gif|jpe?g)\z}
urls.each { |url|
    puts "#{url}: #{(reg =~ url) == 0}"
}

输出:

http://image.com/a.jpg: true
https://image.com/a.jpg: true
ssh://image.com/a.jpg: false
http://image.com/a.jpeg: true
https://image.com/a.png: true
ssh://image.com/a.jpeg: false

【讨论】:

  • 感谢您的解释。非常感谢
【解决方案3】:

这里的答案非常好,但如果您想避免使用复杂的正则表达式并将您的意图更清楚地传达给读者,您可以让URIFile 为您完成繁重的工作。

(由于您使用的是 2.5,所以我们使用 #match? 而不是其他正则表达式匹配方法。)

def valid_url?(url)
  # Let URI parse the URL.
  uri = URI.parse(url)
  # Is the scheme http or https, and does the extension match expected formats?
  uri.scheme.match?(/https?/i) && File.extname(uri.path).match?(/(png|jpe?g|gif)/i)
rescue URI::InvalidURIError
  # If it's an invalid URL, URI will throw this error.
  # We'll return `false`, because a URL that can't be parsed by URI isn't valid.
  false
end

urls.map { |url| [url, valid_url?(url)] }

#=> Results in:
'http://image.com/a.jpg', true
'https://image.com/a.jpg', true
'ssh://image.com/a.jpg', false
'http://image.com/a.jpeg', true
'https://image.com/a.png', true
'ssh://image.com/a.jpeg', false
'https://image.com/a.tif', false
'http://t.co.uk/proposal.docx', false
'not a url', false

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-24
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    相关资源
    最近更新 更多