【问题标题】:Regular expression to remove special characters while retaining a valid email format在保留有效电子邮件格式的同时删除特殊字符的正则表达式
【发布时间】:2014-10-29 20:50:46
【问题描述】:

我在 C# 中使用它。我以这种格式的类似电子邮件的字符串开头:

employee[any characters]@company[any characters].com

我想从 [任何字符] 片段中去除非字母数字。

例如我想要这个"employee1@2 r&a*d.m32@@company98 ';99..com"

变成这个"employee12radm32@company9899.com"

这个表达式简单地去掉了所有的特价商品,但我想在 company 之前留下一个 @ 和一个 .在 com 之前。所以我需要这个表达式来忽略或掩盖员工、@company 和 .com 部分......只是不知道该怎么做。

var regex = new Regex("[^0-9a-zA-Z]"); //whitelist the acceptables, remove all else.

【问题讨论】:

  • Regex 表达式本身可以满足您的需求(除此之外它还会删除@.)——这取决于您的编程语言应该如何使用它。来自var 我假设是javascript?
  • 为什么要变成"employee12radm32@company9899.com"而不是"employee1@2rad.m32company9899.com"
  • @Oriol OP 的第 2 行和第 3 行应该回答您的问题......这始终是起始格式,也是我们想要用它做什么。 “@company”始终是电子邮件域的开头。
  • 我更新了 OP 说这是 C#.. 还改写了我想要它做什么而不是暗示它“会做什么”(=
  • 你怎么会收到这样的垃圾作为输入?如果您提高输入质量而不是尝试自己修复它会怎样?

标签: c# regex regex-negation


【解决方案1】:

您可以使用以下正则表达式:

(?:\W)(?!company|com)

它将替换任何特殊字符,除非它后面跟着company(所以@company 将保留)或com(所以.com 将保留):

employee1@2 r&a*d.m32@@company98 ';99..com

会变成

employee12radm32@company9899.com

见:http://regex101.com/r/fY8jD7/2

请注意,您需要 g 修饰符来替换所有出现的此类不需要的字符。 这是 C# 中的默认设置,因此您只需使用简单的Regex.Replace()

https://dotnetfiddle.net/iTeZ4F


更新:

ofc。正则表达式 (?:\W)(?!com) 就足够了 - 但它仍然会留下像 #com~companion 这样的部分,因为它们也匹配。所以 tis 仍然不能保证输入 - 或者说转换 - 100% 有效。您应该考虑简单地抛出一个验证错误,而不是尝试清理输入以满足您的需求。

即使您也能处理 this 的情况 - 如果 @company.com 出现两次该怎么办?

【讨论】:

  • 感谢 dognose...此时我知道“@company”和 .com 不会出现两次...如果源数据达到这一点,我们将与那些人交谈(= 非常感谢!
【解决方案2】:

您可以简化您的正则表达式并将其替换为

tmp = Regex.Replace(n, @"\W+", "");

其中\w 表示所有字母、数字和下划线,\W\w 的否定版本。 一般来说,最好创建一个允许字符的白名单,而不是尝试预测所有不允许的符号。

【讨论】:

  • 有没有办法让正则表达式忽略字符串“employee”、“@company”和“.com”?
  • 它也会删除@符号
【解决方案3】:

我可能会写这样的东西:

(忽略大小写,如果需要区分大小写请评论)。

DotNetFiddle Example

using System;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var email = "employee1@2 r&a*d.m32@@company98 ';99..com";

        var result = GetValidEmail(email);

        Console.WriteLine(result);
    }


    public static string GetValidEmail(string email)
    {
      var result = email.ToLower();

      // Does it contain everything we need?
      if (email.StartsWith("employee")
          && email.EndsWith(".com")
          && email.Contains("@company"))
      {
        // remove beginning and end.
        result = result.Substring(8, result.Length - 13);
        // remove @company
        var split = result.Split(new string[] { "@company" },
          StringSplitOptions.RemoveEmptyEntries);

        // validate we have more than two (you may not need this)
        if (split.Length != 2)
        {
          throw new ArgumentException("Invalid Email.");
        }

        // recreate valid email
        result = "employee"
          + new string (split[0].Where(c => char.IsLetterOrDigit(c)).ToArray())
          + "@company"
          + new string (split[1].Where(c => char.IsLetterOrDigit(c)).ToArray())
          + ".com";

      }
      else
      {
        throw new ArgumentException("Invalid Email.");
      }

      return result;
    }
}

结果

employee12radm32@company989.com

【讨论】:

  • 我希望避免这样的事情,但如果正则表达式无法处理这种模式,我想它必须这样做。谢谢
【解决方案4】:

您尝试做的是,虽然可能,但使用一个单一的正则表达式模式有点复杂。您可以将此场景分解为更小的步骤。一种方法是提取UsernameDomain 组(基本上是您所描述的[any character]),“修复”每个组,并将其替换为原始组。像这样的:

// Original input to transform.
string input = @"employee1@2 r&a*d.m32@@company98 ';99..com";

// Regular expression to find and extract "Username" and "Domain" groups, if any.
var matchGroups = Regex.Match(input, @"employee(?<UsernameGroup>(.*))@company(?<DomainGroup>(.*)).com");

string validInput = input;

// Get the username group from the list of matches.
var usernameGroup = matchGroups.Groups["UsernameGroup"];

if (!string.IsNullOrEmpty(usernameGroup.Value))
{
    // Replace non-alphanumeric values with empty string.
    string validUsername = Regex.Replace(usernameGroup.Value, "[^a-zA-Z0-9]", string.Empty);

    // Replace the the invalid instance with the valid one.
    validInput = validInput.Replace(usernameGroup.Value, validUsername);
}

// Get the domain group from the list of matches.
var domainGroup = matchGroups.Groups["DomainGroup"];

if (!string.IsNullOrEmpty(domainGroup.Value))
{
    // Replace non-alphanumeric values with empty string.
    string validDomain = Regex.Replace(domainGroup.Value, "[^a-zA-Z0-9]", string.Empty);

    // Replace the the invalid instance with the valid one.
    validInput = validInput.Replace(domainGroup.Value, validDomain);
}

Console.WriteLine(validInput);

将输出employee12radm32@company9899.com

【讨论】:

    【解决方案5】:

    @dognose 提供了一个很棒的正则表达式解决方案。我会在这里保留我的答案作为参考,但我会选择他的答案,因为它更短/更干净。

    var companyName = "company";
    var extension = "com";
    var email = "employee1@2 r&a*d.m32@@company98 ';99..com";
    
    var tempEmail = Regex.Replace(email, @"\W+", "");
    
    var companyIndex = tempEmail.IndexOf(companyName);
    var extIndex = tempEmail.LastIndexOf(extension);
    
    var fullEmployeeName = tempEmail.Substring(0, companyIndex);
    var fullCompanyName = tempEmail.Substring(companyIndex, extIndex - companyIndex);
    
    var validEmail = fullEmployeeName + "@" + fullCompanyName + "." + extension;
    

    【讨论】:

    • 不是真的......我们确定给定的格式将是雇员[任何字符]@company[任何字符].com。我们不知道 [any characters] 中会包含什么,我们只需要从 [any charactes] 部分中删除非字母数字字符。
    • 我想我已经修复了它,可以按照您现在的要求进行操作。
    猜你喜欢
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 1970-01-01
    • 2016-04-02
    • 2019-09-12
    相关资源
    最近更新 更多