Javascript 正则表达式:理解音节计数器代码

Javascript 正则表达式:理解音节计数器代码,javascript,regex,encryption,Javascript,Regex,Encryption,我在这里使用了关于JavaScript音节计数的内容,更具体地说,在我自己的代码中,无论我输入哪个单字或多字字符串,该函数始终能够正确计算音节数 我在正则表达式方面的经验有限,没有足够的先验知识在没有帮助的情况下解读下面代码中到底发生了什么。我不是一个对我从某个地方提取的代码在我不知道它是如何工作的情况下工作而感到高兴的人。是否有人能够清楚地说明下面的新计数(word)函数中发生了什么,并帮助我解释RegEx的用法以及该函数如何能够正确计数音节?许多 function new_count(wor

我在这里使用了关于JavaScript音节计数的内容,更具体地说,在我自己的代码中,无论我输入哪个单字或多字字符串,该函数始终能够正确计算音节数

我在正则表达式方面的经验有限,没有足够的先验知识在没有帮助的情况下解读下面代码中到底发生了什么。我不是一个对我从某个地方提取的代码在我不知道它是如何工作的情况下工作而感到高兴的人。是否有人能够清楚地说明下面的
新计数(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
}
函数新计数(字){
word=word.toLowerCase();//word.downcase!
如果(字长)
匹配三个可能的子字符串:除“l”之外的字母或元音后跟“es”(如“res”或“tes”);“ed”或非元音、非“l”后跟“e”。这些模式必须出现在单词的末尾才能匹配,因为模式末尾有
$
。分组
(?:)
只是一个分组;前导的
?:
就是这样区分的。模式可能会短一点:

/(?:[^laeiouy]es?|ed)$/
在任何情况下,如果模式匹配,所涉及的字符将从单词中删除

那么

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

最后,

/[aeiouy]{1,2}/g
匹配任何一个或两个字符长度的元音(包括“y”)。
g
后缀使其成为全局匹配,因此返回值是由所有此类元音跨度组成的数组。返回数组的长度是音节数(根据此技术)

请注意,单词“poem”和“lion”将被报告为单音节单词,这可能适用于某些英语变体,但并非所有变体


在我看来,我们基本上要计算元音或元音对,还有一些特殊情况。让我们从最后一行开始,这一行可以计算元音和元音对:

return word.match(/[aeiouy]{1,2}/g).length;
这将匹配任何元音或元音对。
[…]
表示a,即,如果我们逐个字符遍历字符串,如果实际字符是其中一个,则我们有一个匹配。
{1,2}
是的数目,即,这意味着我们应该恰好匹配一个或两个这样的字符

其他两行用于特殊情况

word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
此行将删除单词末尾的“音节”,它们是:

  • Xes(其中X不是“laeiouy”中的任何一个,例如“zes”)
  • Xe(其中X不是“laeiouy”中的任何一个,例如“xe”)
(我不确定这句话背后的语法含义,但我想,单词末尾的“音节”,如“-ed”,““-ded”,““-xed”等,实际上并不算在内。) 至于regexp部分:
(?:…)
是一个。我想在这种情况下,这个组是非捕获的并不重要;这只是意味着我们想对整个表达式进行分组,但我们不需要再引用它。但是,我们也可以使用捕获组(即
(…)

[^…]
是一个否定字符类。它意味着,匹配任何字符,而不是此处列出的字符。(与上面提到的(非否定)字符类相比。) 管道符号,即
|
,是运算符,这意味着任何表达式都可以匹配。 最后,
$
锚与或字符串匹配(取决于上下文)

这一行从单词的开头去掉了“y”-s(可能开头的“y”不算作音节——在我看来这是有道理的)。
^
是匹配的锚点或字符串(上面提到的c.f.
$


注意:该算法仅在
word
确实包含一个单词时有效。

同样,它会遗漏许多音节为“-es”的复数形式,如“disks”或“cheeses”,并且有些单词的计数会高于准确值。同样(“sales”=>2)。这只适用于准确度不太重要的上下文。@分号可能目的是将“cheeses”视为“cheese”;比如,可能目的是获取词根(“stem”?)的音节数。我来这里的原因与lol完全相同。RegEx现在让我非常困惑。
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
word = word.replace(/^y/, '');