我想使用Ruby regex匹配不包含字符串'localhost'的URL
根据这里的答案和评论,我将两个解决方案放在一起,这两个解决方案似乎都有效:
解决方案A:
(?!.*localhost)^.*$
Run Code Online (Sandbox Code Playgroud)
示例:http://rubular.com/r/tQtbWacl3g
解决方案B:
^((?!localhost).)*$
Run Code Online (Sandbox Code Playgroud)
示例:http://rubular.com/r/2KKnQZUMwf
问题是我不明白他们在做什么.例如,根据文档,^可以以各种方式使用:
[^abc] Any single character except: a, b, or c
^ Start of line
Run Code Online (Sandbox Code Playgroud)
但我不知道它是如何在这里应用的.
有人可以为我分解这些表达方式,以及它们之间的区别吗?
在这两种情况下,^只是行的开头(因为它没有在字符类中使用).由于两者^和前瞻都是零宽度断言,我们可以在第一种情况下切换它们 - 我认为这使得它更容易解释:
^(?!.*localhost).*$
Run Code Online (Sandbox Code Playgroud)
将^表达式锚定到字符串的开头.然后前瞻从那个位置开始,并试图找到localhost字符串的任何地方("任何地方"由.*前面的处理localhost).如果localhost可以找到,则前瞻的子表达式匹配,因此负前瞻导致模式失败.由于前瞻必然是通过相邻的^这个方式从字符串的开头开始,所以整个模式不能匹配.但是,.*localhost如果不匹配(因此localhost不会出现在字符串中),则前瞻成功,并且.*$只需处理匹配字符串的其余部分.
现在是另一个
^((?!localhost).)*$
Run Code Online (Sandbox Code Playgroud)
这一次,前瞻只检查当前位置(里面没有.*).但是每个角色都会重复前瞻.这样它可以再次检查每个位置.这大致是发生了什么:^确保我们再次从字符串的开头开始.前瞻检查是否localhost在该位置找到了该单词.如果没有,一切都很好,.消耗一个字符.在*随后重复两者的那些步骤.我们现在是字符串中的一个字符,并且前瞻检查第二个字符是否开始单词localhost- 如果没有,则一切都很好,并.消耗另一个字符.这是为字符串中的每个字符完成的,直到我们到达结尾.
在这种特殊情况下,两种方法都是等效的,您可以根据性能(如果重要)或可读性(如果不是;可能是第一种)选择一种方法.但是,在其他情况下,第二个变体是首选,因为它允许您对字符串的固定部分执行此重复,而第一个变体将始终检查整个字符串.