【问题标题】:RegExp for splitting a list of emails into basic components (JavaScript)RegExp 用于将电子邮件列表拆分为基本组件 (JavaScript)
【发布时间】:2018-04-21 23:56:45
【问题描述】:

我几乎可以做到这一点,但不完全。

我有一个 JavaScript 字符串,其中包含一个格式不同的电子邮件列表(没有换行符,为便于阅读而编辑):

var emailList = 'peter@pan.com, 
lucky <jack@pot.com>, 
"William Tell" <billy@tell.com>, 
"John Rambo, III" <johnny@rambo.com>, 
"there, might, be, several, commas inside the quotes" <multiple@commas.com>, 
"yes, this is also a valid email address, can you believe" <yes@this@is@valid.com>'

首先,我需要将此字符串拆分为不同的电子邮件。电子邮件由', '分隔:

peter@pan.com, lucky &lt;jack@pot.com&gt;

', ' 也可能出现在用引号括起来的名称中:

"John Rambo, III" &lt;johnny@rambo.com&gt;

甚至可以在引号内找到多个逗号:

"there, might, be, several, commas inside the quotes" &lt;multiple@commas.com&gt;

第 1 步:替换用引号括起来的 ,

我想用逗号替换 &lt;&lt;&lt;&lt;!!!!&gt;&gt;&gt;&gt; 之类的东西

我已经尝试过这个正则表达式:(".*)(,)(\s.*"), $1&lt;&lt;&lt;&lt;!!!!&gt;&gt;&gt;&gt;$3https://regex101.com/r/baha69/1/,但它没有替换引号内的逗号... :-(

第 2 步:拆分数组并撤消逗号替换

这可以在 JavaScript 中通过拆分和替换轻松完成:

var Array = emailList.split(', ');
Array.forEach(function(element, index, arr) {
  arr[index] = element.replace("<<<<!!!!>>>> ", ", ");
});

此时,我应该有一个这样的数组(没有换行符,为便于阅读而编辑):

Array[0] = 'peter@pan.com'
Array[1] = 'lucky
            <jack@pot.com>'
Array[2] = '"William Tell"
            <billy@tell.com>'
Array[3] = '"John Rambo, III"
            <johnny@rambo.com>'
Array[4] = '"there, might, be, several, commas inside the quotes
            <multiple@commas.com>'
Array[5] = '"yes, this is also a valid email address, can you believe"
            <yes@this@is@valid.com>'

第 3 步:拆分电子邮件地址

现在我必须将每封电子邮件转换为基本组件(没有换行符,为便于阅读而编辑):

Array[0] = {fullName: '',
            firstWord: '', localPart: 'peter', company: 'pan', 
            email: 'peter@pan.com'}
Array[1] = {fullName: 'lucky',
            firstWord: 'lucky', localPart: 'jack', company: 'pot', 
            email: 'jack@pot.com'};
Array[2] = {fullName: 'William Tell',
            firstWord: 'William', localPart: 'billy', company: 'tell',
            email: 'billy@tell.com'};
Array[3] = {fullName: 'John Rambo, III',
            firstWord: 'John', localPart: 'johnny', company: 'rambo',
            email: 'johnny@rambo.com'};
Array[4] = {fullName: 'there, might, be, several, commas inside the quotes', 
            firstWord: 'there', localPart: 'multiple', company: 'commas',
            email: 'multiple@commas.com'};
Array[5] = {fullName: 'yes, this is also a valid email address, can you believe', 
            firstWord: 'yes', localPart: 'yes@this@is', company: 'valid',
            email: 'yes@this@is@valid.com'};

为此,我将使用以下正则表达式:

var firstWord = element.match('/"?(\w*),? .*"?/ig')[1]; 

这行得通! :-) https://regex101.com/r/6Z481l/1

var fullName = element.match('/"?(.*)"? </ig')[1]; 

这不起作用:捕获尾随“:-( https://regex101.com/r/6Z481l/2

var localpart = element.match('/<(.*)@/ig')[1];

这不起作用:peter@pan 中的 peter 未被捕获 :-( https://regex101.com/r/6Z481l/3

var company = element.match('/@(.*)\./ig')[1];

这行得通! :-) https://regex101.com/r/6Z481l/4

var email = element.match('/<(.*@.*)>|(^[^<].*[^>])/ig')[1];

令人惊讶的是,这有效! :-) 但我几乎可以肯定它可以变得更优雅 https://regex101.com/r/6Z481l/5

值得一提的是,电子邮件被认为是经过验证的

所以,我需要一些帮助来完成第 1 步和第 3 步。如果第 3 步中的任何工作正则表达式可以简化或更优雅,我会从中学习!

不是目标,但如果你想出一个神奇的正则表达式,它可以像我需要的那样拆分电子邮件,那么我可以保证你一定会让我赞叹不已,并且因为我缺乏正则表达式知识而让我感到非常渺小! ! :-)

谢谢!

【问题讨论】:

  • var Array = 我强烈建议不要隐藏内置的 Array 对象
  • 如果不是单个单词,全名是否总是用双引号引起来?
  • @CertainPerformance 好点!!我从来没有这样做过,代码中的变量称为stringArray,但它对于 SO 易读性来说太长了,我把它缩短了,留下了Array。我的错!

标签: javascript regex split


【解决方案1】:

我相信您应该能够使用正则表达式获得预期的最终结果:

(?:(?:"?((\w+)\b.*\b)"?)\s)?<?(([\w@]*)@(\w*)\.[a-zA-Z]{2,3})>?,?

并将其替换为:

{ fullName:'\1', firstWord:'\2', localPart:'\4', company:'\5', email:'\3'}

See Demo

【讨论】:

  • 感谢 Matt.G!我进行了修改以更好地解析电子邮件,因为您的解决方案取决于特定数量的 @ 出现。基本上我想解析这样的电子邮件地址: part1@part2.part3 part1 = ANYTHING before the last @ part2 = ANYTHING between the last @ and the last 。 part3 =最后一个之后的任何东西。因此,我将您非常出色的正则表达式修改为:(?:(?:"?((\w+)\b.*\b)"?)\s)?(?:(?:&lt;?((\S+)@((\S+)\.\S+))&gt;?)) 演示:regex101.com/r/Opwq4S/6 经验教训:匹配组、嵌套捕获组和一次性替换。杰出的-!我觉得自己很渺小……
  • 我发现这非常合适:xkcd.com/208 除了我使用的是 JavaScript 而不是 Perl... :-)
【解决方案2】:

您可以用逗号分割字符串,不包括用引号括起来的字符串,例如this:

,(?=(?:[^'"]|'[^']*'|"[^"]*")*$)

这应该可以让您摆脱第 1 步和第 2 步。

关于步骤 3 中的非功能模式:

不起作用:捕获尾随“

  • (?|"(\[^"\]+)"|(.*) &lt;):首先匹配平衡引号,或者&lt;之前的所有内容。
    警告:如果第 1 组为空,则必须检查第 2 组(不幸的是,JS 没有 branch reset 组)。

不起作用:peter@pan 中的 peter 未被捕获

  • (&lt;|^)(.*)@:你可以从头开始二次匹配;
    但是,这很麻烦,因为模式没有正确锚定。

对于电子邮件验证部分,您应该使用existingrecommended 解决方案之一。但我猜这是另一个话题。

【讨论】:

  • 谢谢@wp78de!!这种方法奏效了。我做了一些修改以满足我的适当需求:regex101.com/r/baha69/2
猜你喜欢
  • 2012-09-15
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
  • 2013-05-17
  • 2019-02-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多