RegEx:理解音节计数器代码

时间:2015-02-07 16:46:32

标签: javascript regex encryption

我在这里使用Dylan's question关于JavaScript音节计数,更具体地说artfulhacker's answer,在我自己的代码中,无论我提供哪个单字或多字字符串,该函数始终能够正确计算音节数。

我对RegEx的经验有限,并且没有足够的先验知识来解释以下代码中究竟发生了什么,没有一些帮助。我并不是一个对我从某个地方工作的代码感到高兴的人,而我却不知道 它是如何运作的。有人能够在下面的new_count(word)函数中详细说明发生了什么,并帮助我破译RegEx的使用以及该函数如何能够正确计算音节?很多

function new_count(word) {
  word = word.toLowerCase();                                     //word.downcase!
  if(word.length <= 3) { return 1; }                             //return 1 if word.length <= 3
  word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');   //word.sub!(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')
  word = word.replace(/^y/, '');                                 //word.sub!(/^y/, '')
  return word.match(/[aeiouy]{1,2}/g).length;                    //word.scan(/[aeiouy]{1,2}/).size
}

2 个答案:

答案 0 :(得分:3)

/(?:[^laeiouy]es|ed|[^laeiouy]e)$/

匹配三个可能的子串:除“l”之外的字母或后跟“es”的元音(如“res”或“tes”); “编”;或非元音,非'''后跟“e”。由于模式末尾的$,这些模式必须出现在要匹配的单词的末尾。分组(?: )只是一个分组;领先的?:做出了这种区分。模式本来可以短一些:

/(?:[^laeiouy]es?|ed)$/

会做同样的事情。在任何情况下,如果模式匹配,则从单词中删除所涉及的字符。

然后,

/^y/

匹配单词开头的'y'。如果找到“y”,则将其删除。

最后,

/[aeiouy]{1,2}/g

匹配任何一个或两个字符的元音(包括'y')。 g后缀使其成为全局匹配,因此返回值是一个由所有此类元音跨度组成的数组。返回数组的长度是音节数(根据这种技术)。

请注意,“诗”和“狮子”这两个词会被报告为单音节词,这对于某些英语变体可能是正确的,但不是全部。

Here is a pretty good reference for JavaScript regular expression operators.

答案 1 :(得分:3)

据我所知,我们基本上想用一些特殊情况来计算元音或元音对。让我们从最后一行开始,这样做,即计算元音和对:

return word.match(/[aeiouy]{1,2}/g).length;

这将匹配任何元音或元音对。 [...]表示character class,即如果我们逐个字符地查看字符串,则如果实际字符是其中之一,则匹配。 {1, 2}repetitions的数量,即它意味着我们应该恰好匹配一个或两个这样的字符。

另外两行是针对特殊情况的。

word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');

这一行将删除&#39; syllables&#39;从这个词的结尾,它们是:

  • X es(其中 X 除了&#39; laeiouy &#39;之外的任何内容,例如&#39; < EM> ZES &#39)
  • X e(其中 X 除了任何&#39; laeiouy &#39;之外的所有内容,例如&#39; < EM> XE &#39)

我不确定这背后的语法含义是什么,但我想,这个词的结尾处有&#39;音节,就像&#39; -ed& #39;,&#39; -ded&#39;,&#39; -xed&#39;等等,实际上并非如此。) 至于正则表达式部分:(?:...)non-capturing group。我想在这种情况下,这个群体非捕获并不重要;这只是意味着我们想要对整个表达式进行分组,但是我们不需要再参考它。但是,我们也可以使用捕获组(即(...)

[^...]是一个否定的字符类。这意味着,匹配任何字符,这些都不是这里列出的。 (与上面提到的(非否定的)字符类比较。) 管道符号,即|,是alternation运算符,这意味着任何表达式都可以匹配。 最后,$锚点匹配end of the line或字符串(取决于上下文)。

word = word.replace(/^y/, '');

此行从单词的开头删除了&#39; -s(可能&#39; y&#39;在开头不算作音节 - 这在我看来是有意义的)。 ^是匹配the beginning of the line或上述字符串(c.f。$)的锚点。

注意:只有当word真正包含一个单词时,该算法才有效。