Pergunta

Estou tentando analisar uma string como a seguinte usando uma expressão regular .NET:

H3Y5NC8E-TGA5B6SB-2NVAQ4E0

e retorne o seguinte usando Split:H3Y5NC8E TGA5B6SB 2NVAQ4E0

Eu valido cada caractere em relação a um conjunto de caracteres específico (observe que as letras 'I', 'O', 'U' e 'W' estão ausentes), portanto, usar string.Split não é uma opção.O número de caracteres em cada grupo pode variar e o número de grupos também pode variar.Estou usando a seguinte expressão:

([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}

Isso corresponderá exatamente a 3 grupos de 8 caracteres cada.Mais ou menos irá falhar na partida.Isso funciona na medida em que corresponde corretamente à entrada.No entanto, quando uso o método Split para extrair cada grupo de caracteres, obtenho apenas o grupo final.RegexBuddy reclama que eu repeti o próprio grupo de captura e que deveria colocar um grupo de captura em torno do grupo repetido.No entanto, nenhuma das minhas tentativas de fazer isso alcançou o resultado desejado.Tenho tentado expressões como esta:

(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}

Mas isso não funciona.

Como eu gerei o regex no código, poderia expandi-lo pelo número de grupos, mas esperava uma solução mais elegante.


Observe que o conjunto de caracteres não inclui o alfabeto inteiro.Faz parte de um sistema de ativação de produto.Como tal, quaisquer caracteres que possam ser acidentalmente interpretados como números ou outros caracteres são removidos.por exemplo.As letras 'I', 'O', 'U' e 'W' não estão no conjunto de caracteres.

Os hífens são opcionais, pois o usuário não precisa digitá-los, mas eles podem estar lá se o usuário tiver copiado e colado.

Foi útil?

Solução 2

Eu descobri a resposta que procurava.Aqui está meu código de trabalho:

    static void Main(string[] args)
    {
        string pattern = @"^\s*((?<group>[ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){3}\s*$";
        string input = "H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
        Regex re = new Regex(pattern);
        Match m = re.Match(input);

        if (m.Success)
            foreach (Capture c in m.Groups["group"].Captures)
                Console.WriteLine(c.Value);
    }

Outras dicas

A propósito, você pode substituir a classe de caracteres [ABCDEFGHJKLMNPQRSTVXYZ0123456789] por uma classe de caracteres subtraídos mais legível.

[[A-Z\d]-[IOUW]]

Se você deseja apenas combinar 3 grupos assim, por que não usa esse padrão 3 vezes em seu regex e apenas usa 1, 2, 3 subgrupos capturados para formar a nova string?

([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}

Em PHP eu retornaria (não conheço .NET)

return "$1 $2 $3";

Depois de analisar sua pergunta e as respostas dadas, descobri o seguinte:

RegexOptions options = RegexOptions.None;
Regex regex = new Regex(@"([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})", options);
string input = @"H3Y5NC8E-TGA5B6SB-2NVAQ4E0";

MatchCollection matches = regex.Matches(input);
for (int i = 0; i != matches.Count; ++i)
{
    string match = matches[i].Value;
}

Como o "-" é opcional, não é necessário incluí-lo.Não tenho certeza para que você estava usando o {4} no final?Isso encontrará as correspondências com base no que você deseja e, em seguida, usando MatchCollection você poderá acessar cada correspondência para reconstruir a string.

Por que usar Regex?Se os grupos são sempre divididos por -, você não pode usar Split()?

Desculpe se não era isso que você pretendia, mas sua string sempre tem o hífen separando os grupos, então em vez de usar regex você não poderia usar o método String.Split()?

Dim stringArray As Array = someString.Split("-")

Quais são as características definidoras de um bloco válido?Precisamos saber disso para realmente sermos úteis.

Minha sugestão genérica: valide o conjunto de caracteres em uma primeira etapa, depois divida e analise em um método separado com base no que você espera.Se estiver em um site/aplicativo, você poderá usar a validação ASP Regex no front-end e dividi-la no back-end.

Se você estiver apenas verificando o valor do grupo, com group(i).value, obterá apenas o último.No entanto, se você quiser enumerar todas as vezes que esse grupo foi capturado, use group(2).captures(i).value, conforme mostrado abaixo.

system.text.RegularExpressions.Regex.Match("H3Y5NC8E-TGA5B6SB-2NVAQ4E0","(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]+)-?)*").Groups(2).Captures(i).Value

Mike,

Você pode usar o conjunto de caracteres de sua escolha dentro do grupo de caracteres.Tudo que você precisa é adicionar o modificador "+" para capturar todos os grupos.Veja minha resposta anterior, basta alterar [A-Z0-9] para o que você precisar (ou seja,[ABCDEFGHJKLMNPQRSTVXYZ0123456789])

Você pode usar este padrão:

Regex.Split("H3Y5NC8E-TGA5B6SB-2NVAQ4E0", "([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}+)-?")

Mas você precisará filtrar as strings vazias do array resultante.Citação de MSDN:

Se várias correspondências forem adjacentes umas às outras, uma string vazia será inserida na matriz.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top