Expresión regular, dividir cadena por mayúscula pero ignorar TLA

Estoy usando la expresión regular

System.Text.RegularExpressions.Regex.Replace(stringToSplit, "([AZ])", " $1").Trim() 

para dividir cadenas por mayúscula, por ejemplo:

‘MyNameIsSimon’ se convierte en ‘My Name Is Simon’

Encuentro esto increíblemente útil cuando trabajo con enumeraciones. Lo que me gustaría hacer es cambiarlo ligeramente para que las cadenas solo se dividan si la siguiente letra es una letra minúscula, por ejemplo:

‘USAToday’ se convertiría en ‘USA Today’

Se puede hacer esto?

EDITAR: Gracias a todos por responder. Puede que no haya pensado completamente en esto, en algunos casos ‘A’ y ‘I’ tendrían que ser ignorados, pero esto no es posible (al menos no de una manera significativa). En mi caso, las respuestas a continuación hacen lo que necesito. ¡Gracias!

 ((? <= [az]) [AZ] | [AZ] (? = [az]))

o su primo consciente de Unicode

 ((? <= \ p {Ll}) \ p {Lu} | \ p {Lu} (? = \ p {Ll}))

cuando se reemplaza globalmente con

 " $1" 

maneja

 TodayILiveInTheUSAConSimon
 EE.UU. Hoy en día
 IAmSOOOBored

flexible

  Hoy vivo en los Estados Unidos con Simon
 EE.UU. Hoy en día
 Estoy tan aburrido

En un segundo paso, tendrías que recortar la cuerda.

cualquier carácter en mayúsculas que no esté seguido de un carácter en mayúsculas:

 Replace(string, "([AZ])(?![AZ])", " $1") 

Editar:

Me di cuenta de que estás usando esto para enumeraciones. Realmente no aliento el uso de representaciones de cadenas de enumeraciones como esta, y los problemas a mano son una buena razón por qué. Eche un vistazo a esto en su lugar: http://www.refactoring.com/catalog/replaceTypeCodeWithClass.html

Puede pensar en cambiar las enumeraciones; Las pautas de encoding de MS sugieren acrónimos de cassette Pascal como si fueran palabras; XmlDocument , HtmlWriter , etc. Los HtmlWriter dos letras no siguen esta regla; System.IO .

Entonces deberías usar UsaToday , y tu problema desaparecerá.

Espero que esto te ayude a dividir una cadena por sus letras mayúsculas y mucho más. Puedes intentar usar Humanizer , que es un paquete nuget gratuito. Esto le ahorrará más problemas con letras, oraciones, números, cantidades y mucho más en muchos idiomas. Consulte esto en: https://www.nuget.org/packages/Humanizer/

La expresión de Tomalak funcionó para mí, pero no con la función Replace incorporada. Regex.Replace() , sin embargo, funcionó.

 For i As Integer = 0 To names.Length - 1 'Worked names(i) = Regex.Replace(names(i), "((?<=[az])[AZ]|[AZ](?=[az]))", " $1").TrimStart() ' Didn't work 'names(i) = Replace(names(i), "([AZ])(?=[az])|(?<=[az])([AZ])", " $1").TrimStart() Next 

Por cierto, estoy usando esto para dividir las palabras en nombres de enumeración para mostrar en la interfaz de usuario y funciona muy bien.

Nota: No leí la pregunta lo suficientemente bien, USAToday devolverá “Hoy”; por lo que este awser no es el correcto.

  public static List SplitOnCamelCase(string text) { List list = new List (); Regex regex = new Regex(@"(\p{Lu}\p{Ll}+)"); foreach (Match match in regex.Matches(text)) { list.Add (match.Value); } return list; } 

Esto coincidirá con “WakeOnBoot” como “Wake On Boot” y no devuelve nada en NMI o TLA

Mi versión que también maneja expresiones aritméticas simples:

 private string InjectSpaces(string s) { var patterns = new string[] { @"(?<=[^AZ,&])[AZ]", // match capital preceded by any non-capital except ampersand @"(?<=[AZ])[AZ](?=[az])", // match capital preceded by capital and followed by lowercase letter @"[\+\-\*\/\=]", // match arithmetic operators @"(?<=[\+\-\*\/\=])[0-9,\(]" // match 0-9 or open paren preceded by arithmetic operator }; var pattern = $"({string.Join("|", patterns)})"; return Regex.Replace(s, pattern, " $1"); }