gpt4 book ai didi

ruby - 如何 .{n} 和 ?

转载 作者:数据小太阳 更新时间:2023-10-29 08:50:27 25 4
gpt4 key购买 nike

我试图了解如何.{n}?<option>:工作于 Regexp在 Ruby 1.9.3 环境中。但无法理解以下代码如何产生输出:

irb(main):001:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{2}(?m:.)\Z/
=> ["fin\n", "fin\r\n", "find"]
irb(main):002:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> ["fin\n", "fi\n\n"]
irb(main):003:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> []
irb(main):010:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\Z/
=> ["fin\n", "fi\n\n"]
irb(main):011:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(m:.)\Z/
=> []
irb(main):012:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> []

任何人都可以帮助我理解上面的代码是如何在 IRB 中生成上述输出的吗?终端?

谢谢,

根据@Kevin 最后一段我在下面尝试并找到了预期和理想的输出:
irb(main):014:0> %W{fin fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> ["fin"]
irb(main):015:0> %W{fin fi\n\n \n\n fin\r find}.grep /f.(?m:.)\z/
=> ["fin"]
irb(main):016:0> %W{fin fi\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> ["fin", "fi\n"]
irb(main):017:0> %W{fin fi\n \n\n fr\n find}.grep /f.(?m:.)\z/
=> ["fin", "fi\n", "fr\n"]
irb(main):018:0>

非常感谢 @凯文 .你帮助我理解了整个概念!

最佳答案

{n}表示“重复前一个原子 n 次”。在正则表达式中,原子是一个独立的单元。所以单个字符是一个原子。一个点也是如此。一个组也是一个原子(包含其他原子),就像一个字符类。所以.{n}表示“匹配 n 个字符”(因为 . 表示“匹配任何字符”)。

请注意 {n}不像反向引用,因为它不必在每次重复时匹配相同的文本。 .{5}行为与 ..... 完全一样.

这个构造也更强大。它可以采用两个数字,并且匹配整个范围的重复计数。所以.{3,5}表示“匹配 3 到 5 个字符”。和 .{3,}表示“匹配 3 个或更多字符”。 ?可以换成{0,1} , *{0,} , 和 +{1,}如果你愿意。
?<option:其实不是一回事。它是 (?<option>:<pattern>) ,这会打开 <option> 中列出的所有标志在 <pattern> 期间.它就像一个组,只是它实际上并不创建反向引用。所以表达式 (?m:.)意思是“匹配一个字符,就像标志 m 被打开一样”。鉴于 m 的行为正如 nhahtdh 在评论中所说的“匹配\n”,表达式 .(?m:.).意思是“匹配除换行符之外的任何字符,然后是任何字符,然后是除换行符之外的任何字符”。

这种构造有两个好处。首先,它允许您只将一个标志应用于模式的一部分,这偶尔会很有用。其次,如果您将整个模式包装在这个构造中,那么您就可以控制应用于正则表达式的标志,而不管该表达式在哪里使用。当您以用户身份提供正则表达式并且无法控制程序源时,这很有用。

让我们来看看你给出的例子:

> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{2}(?m:.)\Z/
=> ["fin\n", "fin\r\n", "find"]

您的图案 /f.{2}(?m:.)\Z/表示“匹配 f,后跟 2 个任何字符(但换行符),后跟任何字符,并 anchor 定到字符串的末尾或刚好在换行符之前”。

因此,在 3 场比赛中的每一场比赛中, fin匹配 f.{2} . (?m:.)匹配 \n在第一个, \r在第二个,和 d在第三。和 \Z匹配第一个字符串的结尾,就在第二个换行符之前,以及第三个字符串的结尾。
fi\n\n不匹配,因为第一个 \n这里不能匹配 .来自 .{2}没有 m旗帜。
> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> ["fin\n", "fi\n\n"]

这里 fi匹配 f.{1}在这两种情况下。 (?m:.)匹配 n\n , 和 \Z在这两种情况下,在换行符之前匹配。
fin\r\n不匹配,因为 \Z只会在字符串中的最后一个换行符之前匹配,而不是在 CRLF 对之前匹配。和 find不匹配,因为没有什么可以匹配 d .
> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> []

我认为你在这里有一个复制和粘贴错误。这与之前的模式相同,并与之匹配。
> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\Z/
=> ["fin\n", "fi\n\n"]

这也与之前的模式相同。 ..{1}是一样的。事实上, {1}总是可以从任何正则表达式中剥离而不改变任何东西。
> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(m:.)\Z/
=> []

你掉了 ?在这个模式中,改变了 (m:.) 的含义.这不再更改选项。现在它只是一个匹配模式 m:. 的捕获组,这当然不会出现在您的输入中。
> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> []

你改了 \Z\z这里。这两者的区别是 \Z可以在尾随换行符之前匹配,但 \z必须只匹配字符串的结尾。如果无法在尾随换行符之前匹配,则此处的所有输入都不匹配。但是,例如,如果您有 fin (不带换行符)或 fi\n (没有第二个换行符)它会起作用。

关于ruby - 如何 .{n} 和 ?<option> : works in `Regexp` on Ruby 1. 9.3 环境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14385763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com